在C++性能优化领域,"将计算尽可能转移到编译期"是一条黄金法则。编译期计算(Compile-Time Computation)能显著减少程序运行时的开销,提升执行效率,同时还能在编译阶段暴露潜在错误。C++11引入的constexpr关键字及其后续演进(C++14/17/20),为开发者提供了一套完整的编译期计算工具链,彻底改变了传统模板元编程的复杂局面。

本文将从constexpr的基础语法出发,系统讲解其在变量、函数、类中的应用,深入分析编译期计算的实现原理与性能优势,并通过实战案例展示如何利用constexpr解决实际开发中的性能瓶颈,帮助开发者充分发挥编译期计算的潜力。

一、编译期计算与constexpr概述

1.1 什么是编译期计算?

编译期计算指在程序编译阶段完成的计算,其结果直接嵌入到生成的二进制代码中,而非在程序运行时动态计算。例如,3 + 5在编译期即可计算为8,无需在运行时执行加法指令。

传统C++中,编译期计算依赖:

  • 字面量常量(如423.14
  • enum枚举常量
  • 模板元编程(TMP)的编译期递归

但这些方式存在明显局限:模板元编程语法晦涩,枚举常量功能有限,难以实现复杂计算。constexpr的出现彻底改变了这一局面。

1.2 constexpr的核心价值

constexpr(常量表达式)是C++11引入的关键字,用于声明可在编译期求值的表达式或函数。其核心价值体现在:

  1. 性能提升:将计算从运行时转移到编译期,减少程序启动时间和运行时开销。
  2. 类型安全:编译期计算的结果是常量,可用于数组大小、模板参数等需要编译期常量的场景。
  3. 错误检测:编译期计算能在编译阶段暴露计算逻辑错误,避免运行时崩溃。
  4. 代码简化:替代复杂的模板元编程,用接近普通代码的语法实现编译期计算。

1.3 constexpr的版本演进

constexpr并非一成不变,其功能随C++标准不断增强:

标准版本核心增强点示例
C++11引入constexpr,支持简单函数(单return语句,无循环)constexpr int add(int a, int b) { return a + b; }
C++14放宽限制:允许函数内有局部变量、循环、多return语句constexpr int factorial(int n) { int res=1; for(int i=2;i<=n;++i) res*=i; return res; }
C++17支持if constexpr(编译期条件分支)、std::array等容器的编译期操作constexpr auto get_val(bool b) { if constexpr(b) return 1; else return 2.0; }
C++20大幅扩展:支持constexpr动态内存分配、lambda表达式、虚函数等constexpr auto make_vec() { std::vector<int> v={1,2}; return v; }

现代C++中,constexpr已成为编译期计算的首选工具,功能强大且语法简洁。

二、constexpr基础:变量与函数

2.1 constexpr变量

constexpr变量是编译期可求值的常量,必须满足:

  • 声明时初始化
  • 初始化表达式是常量表达式
  • 类型是字面类型(Literal Type,可在编译期构造的类型)
基本用法
#include <iostream>int main() {// 基础类型constexpr变量constexpr int a = 10;  // 正确:初始化表达式是常量constexpr int b = a * 2;  // 正确:a是constexpr,表达式是常量// 错误示例// int c = 20;// constexpr int d = c;  // 错误:c不是常量表达式// 用于需要编译期常量的场景int arr[a];  // 正确:a是constexpr,可作为数组大小(C99变长数组的C++常量替代)std::cout << "数组大小:" << sizeof(arr)/sizeof(int) << "\n";  // 输出:10return 0;
}
constexpr与const的区别

constconstexpr都可用于声明常量,但本质不同:

  • const:表示变量"只读",初始化表达式可在运行时求值(如const int x = rand();)。
  • constexpr:表示变量"编译期可求值",初始化表达式必须是常量表达式。
const int x = 10;  // 可能在编译期或运行时初始化(取决于上下文)
constexpr int y = 10;  // 必须在编译期初始化const int z = x + y;  // z是const,但初始化依赖x和y(若x是运行时常量,z也是运行时常量)
constexpr int w = x + y;  // 仅当x和y都是constexpr时才合法

结论:constexpr是"更强的const"——所有constexpr变量都是const,但并非所有const变量都是constexpr

2.2 constexpr函数

constexpr函数是可在编译期或运行时调用的函数。当传入的参数是常量表达式时,函数在编译期求值;当传入运行时变量时,函数在运行时求值。

C++11中的constexpr函数(基础版)

C++11对constexpr函数有严格限制:

  • 函数体只能有一条return语句
  • 不能包含局部变量(除参数外)
  • 不能有循环、分支(if)等控制流语句
  • 只能调用其他constexpr函数
// C++11兼容的constexpr函数
constexpr int add(int a, int b) {return a + b;  // 单return语句,无其他逻辑
}constexpr int square(int x) {return x * x;  // 调用乘法运算符(隐式constexpr)
}int main() {constexpr int res1 = add(3, 5);  // 编译期求值:8int x = 4;int res2 = add(x, 5);  // 运行时求值:x + 5(x是变量)static_assert(res1 == 8, "编译期断言失败");  // 正确:res1是编译期常量return 0;
}
C++14对constexpr函数的扩展

C++14大幅放宽了constexpr函数的限制,使其更接近普通函数:

  • 允许局部变量(必须是constexpr或初始化后不再修改)
  • 允许循环(forwhile
  • 允许多return语句
  • 允许条件分支(if-else
// C++14起支持的constexpr函数(含循环)
constexpr int factorial(int n) {if (n <= 1) return 1;  // 条件分支int res = 1;  // 局部变量for (int i = 2; i <= n; ++i) {  // 循环res *= i;}return res;  // 多return路径
}int main() {constexpr int f5 = factorial(5);  // 编译期求值:120int n = 6;int f6 = factorial(n);  // 运行时求值:720(n是变量)static_assert(f5 == 120, "阶乘计算错误");  // 正确return 0;
}

这一扩展使constexpr函数的实用性大幅提升,基本可替代简单的模板元编程。

C++17的if constexpr(编译期条件分支)

C++17引入if constexpr,允许在constexpr函数中根据编译期条件选择执行路径,未选中的分支会被编译器完全忽略(而非仅不执行)。

#include <type_traits>// 根据类型选择不同的编译期计算逻辑
template <typename T>
constexpr auto compute(T val) {if constexpr (std::is_integral_v<T>) {return val * 2;  // 整数类型:乘以2} else if constexpr (std::is_floating_point_v<T>) {return val / 2.0;  // 浮点类型:除以2} else {return val;  // 其他类型:直接返回}
}int main() {constexpr int res1 = compute(10);  // 编译期求值:20(整数分支)constexpr double res2 = compute(3.14);  // 编译期求值:1.57(浮点分支)constexpr const char* res3 = compute("hello");  // 编译期求值:"hello"(其他分支)static_assert(res1 == 20 && res2 == 1.57, "计算错误");return 0;
}

if constexpr与普通if的核心区别:普通if的所有分支都需编译通过(即使运行时不执行),而if constexpr的未选中分支可包含语法正确但不匹配当前类型的代码(如对整数类型调用size()方法)。

三、constexpr进阶:类与数据结构

constexpr不仅适用于变量和函数,还可用于类、构造函数、成员函数,实现编译期的对象创建和操作。

3.1 constexpr构造函数与constexpr对象

C++11起,类可定义constexpr构造函数,用于在编译期创建对象。constexpr构造函数需满足:

  • 函数体只能初始化成员变量(C++11),或包含简单逻辑(C++14起)
  • 所有成员变量必须在初始化列表中初始化(C++11)
  • 不能有virtual函数(C++20前)
// 带constexpr构造函数的类
class Point {
private:int x_, y_;
public:// constexpr构造函数(C++11起支持)constexpr Point(int x, int y) : x_(x), y_(y) {}  // 仅初始化成员变量// constexpr成员函数(返回成员变量)constexpr int x() const { return x_; }constexpr int y() const { return y_; }// C++14起:constexpr成员函数可修改成员变量(需对象是mutable或在编译期修改)constexpr void set_x(int x) { x_ = x; }
};int main() {// 编译期创建Point对象constexpr Point p1(3, 4);static_assert(p1.x() == 3 && p1.y() == 4, "初始化错误");// 编译期修改对象(C++14起)constexpr Point p2(0, 0);constexpr Point p3 = [](){ Point p(0, 0);p.set_x(5);  // 调用constexpr成员函数修改xreturn p;}();  // 立即调用的constexpr lambda(C++17起)static_assert(p3.x() == 5, "修改错误");return 0;
}

3.2 constexpr与标准容器

C++17起,部分标准容器(如std::arraystd::string_view)支持constexpr操作,可在编译期创建和操作:

#include <array>
#include <string_view>// 编译期初始化std::array并计算总和
constexpr auto make_array_and_sum() {std::array<int, 5> arr = {1, 2, 3, 4, 5};  // constexpr容器int sum = 0;for (int i = 0; i < arr.size(); ++i) {sum += arr[i];  // 编译期遍历}return sum;
}// 编译期字符串处理(C++17 string_view)
constexpr bool starts_with_hello(std::string_view s) {return s.substr(0, 5) == "hello";  // 编译期字符串比较
}int main() {constexpr int total = make_array_and_sum();static_assert(total == 15, "数组求和错误");constexpr bool res1 = starts_with_hello("hello world");  // trueconstexpr bool res2 = starts_with_hello("hi there");  // falsestatic_assert(res1 && !res2, "字符串判断错误");return 0;
}

C++20进一步扩展了constexpr对容器的支持,std::vectorstd::string等动态容器也可在编译期使用(需注意:编译期动态内存分配在程序运行时会被优化掉,不会产生实际的堆操作)。

3.3 自定义constexpr数据结构

结合constexpr函数和类,可实现编译期可用的自定义数据结构,如链表、栈、队列等:

// 编译期链表节点
template <int Val, typename Next = void>
struct Node {static constexpr int value = Val;using next = Next;
};// 编译期链表长度计算
template <typename List>
constexpr int length() {if constexpr (std::is_same_v<typename List::next, void>) {return 1;  // 尾节点} else {return 1 + length<typename List::next>();  // 递归计算}
}// 编译期链表求和
template <typename List>
constexpr int sum() {if constexpr (std::is_same_v<typename List::next, void>) {return List::value;} else {return List::value + sum<typename List::next>();}
}int main() {// 编译期构建链表:1 -> 2 -> 3using List = Node<1, Node<2, Node<3>>>;constexpr int len = length<List>();  // 3constexpr int total = sum<List>();   // 6static_assert(len == 3 && total == 6, "链表操作错误");return 0;
}

四、编译期计算实战案例

constexpr的应用场景广泛,从简单的常量定义到复杂的编译期算法,都能发挥重要作用。以下是几个典型实战案例:

4.1 编译期素数判断与素数表生成

素数判断是经典的计算密集型任务,将其转移到编译期可显著提升运行时性能:

#include <array>// 编译期判断是否为素数
constexpr bool is_prime(int n) {if (n <= 1) return false;if (n == 2) return true;if (n % 2 == 0) return false;for (int i = 3; i * i <= n; i += 2) {  // 仅检查奇数if (n % i == 0) return false;}return true;
}// 编译期生成前N个素数的数组
template <int N>
constexpr auto generate_primes() {std::array<int, N> primes{};int count = 0;int num = 2;while (count < N) {if (is_prime(num)) {primes[count++] = num;}num++;}return primes;
}int main() {// 编译期生成前10个素数constexpr auto primes = generate_primes<10>();// 运行时直接使用编译期结果for (int p : primes) {std::cout << p << " ";  // 输出:2 3 5 7 11 13 17 19 23 29}return 0;
}

这一案例中,generate_primes<10>()在编译期完成计算,运行时仅需遍历数组,避免了重复计算。

4.2 编译期字符串哈希

字符串哈希常用于哈希表、缓存键等场景,编译期计算哈希值可在运行时直接使用,提升效率:

// 编译期字符串哈希(FNV-1a算法)
constexpr uint32_t fnv1a_hash(const char* str, uint32_t hash = 0x811c9dc5) {return (*str == '\0') ? hash : fnv1a_hash(str + 1, (hash ^ static_cast<uint32_t>(*str)) * 0x01000193);
}int main() {// 编译期计算哈希值constexpr uint32_t hash1 = fnv1a_hash("hello");constexpr uint32_t hash2 = fnv1a_hash("world");// 运行时比较哈希值(直接比较常量)if (hash1 == fnv1a_hash("hello")) {  // 编译期已知truestd::cout << "哈希匹配\n";}return 0;
}

在实际应用中,可将编译期哈希与switch语句结合,实现高效的字符串分支判断(传统switch不支持字符串,但支持整数哈希值)。

4.3 编译期配置校验

在大型项目中,配置参数的合法性校验可放在编译期,避免运行时因配置错误导致崩溃:

// 编译期配置结构体
struct Config {int max_connections;  // 最大连接数(必须>0且<=1000)int timeout_ms;       // 超时时间(必须>=100ms)bool enable_log;      // 是否启用日志
};// 编译期校验配置合法性
constexpr bool validate_config(const Config& cfg) {bool valid = true;if (cfg.max_connections <= 0 || cfg.max_connections > 1000) {valid = false;}if (cfg.timeout_ms < 100) {valid = false;}return valid;
}// 安全创建配置(仅当配置合法时编译通过)
template <Config Cfg>
constexpr Config make_safe_config() {static_assert(validate_config(Cfg), "配置不合法!");return Cfg;
}int main() {// 合法配置:编译通过constexpr Config valid_cfg = make_safe_config<Config{500, 200, true}>();// 非法配置:编译失败(触发static_assert)// constexpr Config invalid_cfg = make_safe_config<Config{-1, 50, false}>();return 0;
}

这一模式在嵌入式开发、驱动程序等对可靠性要求高的场景中尤为重要。

4.4 编译期矩阵运算

科学计算中的矩阵运算(如乘法、转置)可在编译期完成,尤其适合固定大小的小矩阵:

#include <array>// 编译期矩阵转置(N行M列 -> M行N列)
template <typename T, int N, int M>
constexpr auto transpose(const std::array<std::array<T, M>, N>& mat) {std::array<std::array<T, N>, M> res{};for (int i = 0; i < N; ++i) {for (int j = 0; j < M; ++j) {res[j][i] = mat[i][j];}}return res;
}// 编译期矩阵乘法(N×M 乘以 M×P -> N×P)
template <typename T, int N, int M, int P>
constexpr auto multiply(const std::array<std::array<T, M>, N>& a, const std::array<std::array<T, P>, M>& b) {std::array<std::array<T, P>, N> res{};for (int i = 0; i < N; ++i) {for (int j = 0; j < P; ++j) {for (int k = 0; k < M; ++k) {res[i][j] += a[i][k] * b[k][j];}}}return res;
}int main() {// 编译期定义矩阵constexpr std::array<std::array<int, 2>, 2> a = {{{1, 2},{3, 4}}};// 编译期转置constexpr auto a_t = transpose(a);  // 2×2矩阵转置// 编译期乘法(a × a_t)constexpr auto a_mul_at = multiply(a, a_t);// 验证结果(编译期断言)static_assert(a_mul_at[0][0] == 5 && a_mul_at[1][1] == 25, "矩阵运算错误");return 0;
}

五、constexpr的性能分析与限制

5.1 编译期计算vs运行时计算:性能对比

编译期计算的核心优势是零运行时开销,但可能增加编译时间。以下是一个性能对比示例:

#include <chrono>
#include <iostream>// 斐波那契数列计算(递归实现)
constexpr int fib(int n) {return (n <= 1) ? n : fib(n - 1) + fib(n - 2);
}int main() {// 编译期计算fib(30)constexpr int fib30_compile = fib(30);// 运行时计算fib(30)auto start = std::chrono::high_resolution_clock::now();int fib30_runtime = fib(30);auto end = std::chrono::high_resolution_clock::now();std::cout << "编译期结果:" << fib30_compile << "\n";std::cout << "运行时结果:" << fib30_runtime << "\n";std::cout << "运行时耗时:" << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()<< " us\n";  // 约数百微秒(递归实现效率低)return 0;
}

运行结果显示:编译期计算的结果直接可用,运行时无需消耗时间。对于多次调用的场景(如循环中调用fib(30)),编译期计算的优势更明显。

5.2 编译时间与运行时间的平衡

编译期计算并非"计算量越大越好",过度复杂的编译期计算会显著增加编译时间,降低开发效率。平衡原则:

  1. 小数据量、高频调用:优先编译期计算(如配置参数、常量哈希)。
  2. 大数据量、低频调用:倾向运行时计算(如大型矩阵运算、复杂字符串处理)。
  3. 开发迭代快的项目:控制编译期计算复杂度,避免每次编译耗时过长。
  4. 发布版本:可启用更复杂的编译期优化,提升最终产品性能。

5.3 constexpr的当前限制

尽管constexpr功能不断增强,仍存在一些限制(随标准演进逐步减少):

  1. C++20前不支持动态内存管理new/delete在C++20前不能用于constexpr函数。
  2. 虚函数支持有限:C++20起允许constexpr虚函数,但实现复杂且效率可能不高。
  3. I/O操作不可用:编译期计算不能进行文件读写、控制台输出等I/O操作。
  4. 部分标准库函数不支持:并非所有标准库函数都标记为constexpr(如std::sort在C++20起支持constexpr)。
  5. 调试困难:编译期计算的错误信息通常不如运行时调试直观,需依赖static_assert辅助。

六、最佳实践与调试技巧

6.1 constexpr使用最佳实践

  1. 优先使用constexpr替代宏:宏缺乏类型检查,constexpr常量更安全。

    #define MAX_SIZE 100  // 不推荐
    constexpr int max_size = 100;  // 推荐
    
  2. 函数参数尽量使用值传递constexpr函数的参数需在编译期确定,值传递更易满足常量表达式要求。

  3. 结合auto推导返回类型:复杂constexpr函数的返回类型难以手动声明,auto可简化代码。

    constexpr auto complex_calc(int x) {// 复杂计算...return result;  // auto自动推导类型
    }
    
  4. 用static_assert验证编译期计算结果:在开发阶段确保计算逻辑正确。

    constexpr int res = my_constexpr_func(5);
    static_assert(res == 25, "计算错误:预期25");  // 提前暴露错误
    
  5. 避免在constexpr函数中使用全局变量:全局变量可能不是编译期常量,导致函数无法在编译期求值。

6.2 调试constexpr代码的技巧

constexpr代码的调试比普通代码更困难(无法在编译期设置断点),可采用以下技巧:

  1. 分步验证:将复杂constexpr函数拆分为多个小函数,用static_assert验证中间结果。

    constexpr int step1(int x) { /* ... */ }
    constexpr int step2(int x) { /* ... */ }
    constexpr int complex_func(int x) { return step2(step1(x)); }static_assert(step1(5) == 10, "step1错误");  // 验证中间步骤
    static_assert(complex_func(5) == 20, "最终结果错误");
    
  2. 运行时复现编译期逻辑:编写与constexpr函数逻辑一致的普通函数,在运行时调试后再迁移。

    // 先调试普通函数
    int factorial_runtime(int n) { /* 与constexpr版本相同 */ }// 确认正确后改为constexpr
    constexpr int factorial(int n) { /* 同上 */ }
    
  3. 利用编译器诊断信息:现代编译器(如GCC 10+、Clang 12+)对constexpr错误的提示越来越清晰,仔细分析错误信息通常能定位问题。

  4. 限制编译期计算深度:递归constexpr函数若深度过深,可能触发编译器的递归限制(可通过编译器参数调整,如GCC的-fconstexpr-depth=10000)。

七、总结

constexpr是C++编译期计算的核心工具,从C++11的基础常量表达式到C++20的全面增强,它彻底改变了开发者处理编译期逻辑的方式。通过将计算从运行时转移到编译期,constexpr不仅能提升程序性能,还能在编译阶段暴露错误,增强代码可靠性。

随着C++标准的持续演进,constexpr的功能将进一步完善,有望覆盖更多编译期计算场景。掌握constexpr已成为现代C++开发者提升代码质量和性能的必备技能,无论是系统开发、游戏引擎还是嵌入式编程,编译期计算都能发挥关键作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88913.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88913.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/88913.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【micro:bit】从入门到放弃(一):在线、离线版本的使用

1、离线版 micro:bit 1)下载地址 https://makecode.microbit.org/offline-app 2)双击安装包,makecode-microbit-setup-win64.exe,自动安装,安装成功后图标如下图所示 3)运行程序,查看版本信息 4)主界面如下 5)编程界面 点击“新建项目”或者“导入”进入编程界…

Flink Forward Asia 2025 主旨演讲精彩回顾

作为 Apache Flink 社区备受瞩目的年度盛会之一&#xff0c;由阿里云承办的 Flink Forward Asia 2025 于 7 月 3 日在新加坡正式拉开帷幕。From Real-Time Data Analytics to Real-Time AI&#xff0c;Flink 生态全面拥抱 AI本次大会上&#xff0c;Apache Flink 中文社区发起人…

车道偏离预警(LDW)功能介绍

车道偏离预警&#xff08;LDW&#xff09;功能介绍 LDW功能 通过摄像头监测前方车道线&#xff0c;当车辆偏离车道线时&#xff0c;系统发出报警提醒。 系统框图报警条件 最早报警线最迟报警线报警临界线 设置在 最早/最迟报警线 之间接口定义 输入/输出系统算法 横向偏离速度模…

软考(软件设计师)计算机网络-网络层

obsidian做markdown笔记太爽了&#xff0c;康奈尔模板笔记看起来舒服&#xff0c;CSDN试了几种方式&#xff0c;不支持&#xff0c;只能贴图了&#xff0c;将就看吧&#x1f60f;&#xff08;狗头保命&#xff09;工作原理图解 #mermaid-svg-e5Tgpt26jUftujKn {font-family:&qu…

nginx反向代理实现跨域请求

记录一个项目中遇到的跨域请求问题&#xff0c;解决跨域问题无非几种办法&#xff1a;1、后端解决&#xff0c;推荐的做法&#xff0c;可以看我之前写的文章&#xff0c;fastadmin的后台配置跨域&#xff1b;2、前端配置proxy代理&#xff08;开发环境用&#xff09;&#xff1…

利用Wisdom SSH高效搭建CI/CD工作流

在软件开发流程中&#xff0c;CI/CD工作流对于提升效率与确保质量起着关键作用。Wisdom SSH作为一款强大工具&#xff0c;其官网为ssh.wisdomheart.cn&#xff0c;借助AI助手能大幅简化CI/CD工作流的搭建过程。假设服务器已完成基础配置&#xff0c;下面为您介绍如何利用Wisdom…

深度学习-循环神经网络RNN

文章目录序列模型循环神经网络案例词的表示输出的表示矩阵运算表示交叉熵损失时间反向传播算法BPTT梯度消失与梯度爆炸GRULSTM总结序列模型 循环神经网络 st是上一个隐层的输出&#xff0c;体现序列数据之间有很强的关联性。 案例 > S0是初始输入&#xff0c;一般是0&#…

【Linux网络编程】Socket - TCP

目录 V1版本 - Echo Server 初始化服务器 启动服务器 客户端 一些BUG与问题 解决服务器无法一次处理多个请求的问题 多进程版本 多线程版本 线程池版本 V2版本 - 多线程远程执行命令 V1版本 - Echo Server 初始化服务器 TCP大部分内容与UDP是相同的&#xff0c;我们…

知识图谱构建简单分享

最近系统性地学习了知识图谱构建的关键技术&#xff0c;并结合医疗领域知识&#xff0c;完成了一个医疗知识图谱项目的实践。以下是整理的项目架构&#xff0c;欢迎交流指正。说明&#xff1a;当前项目实际实现主要应用了数据预处理、模型设计与预训练、模型优化与测试等核心技…

MCU中的系统控制器(System Controller)是什么?

MCU中的系统控制器&#xff08;System Controller&#xff09;是什么&#xff1f; 在微控制器&#xff08;MCU&#xff09;中&#xff0c;系统控制器&#xff08;System Controller&#xff09;是一个关键模块&#xff0c;负责管理和协调MCU内部的核心功能&#xff0c;确保系统…

【Datawhale夏令营】用AI做带货视频评论分析

文本分类、文本聚类 基础库&#xff1a; pandas, sklearn功能&#xff1a; 商品识别、情感分析、评论聚类商品识别&#xff1a; 视频文本信息&#xff0c;预测推广商品名称 & 情感分析&#xff1a;四个维度&#xff08;情感倾向、用户场景、用户疑问、用户建议&#xff09…

[Meetily后端框架] AI摘要结构化 | `SummaryResponse`模型 | Pydantic库 | vs marshmallow库

第3章&#xff1a;摘要数据结构&#xff08;Pydantic库&#xff09; 欢迎回来&#xff01; 在之前的第2章&#xff1a;API文档中&#xff0c;我们知道API网关提供了端点 而API文档准确告诉我们如何与这些端点通信&#xff0c;包括需要发送的数据格式和期望接收的数据格式。 …

深度学习 tensor及其相关操作

目录 Tensor 概念 数据类型 创建tensor 基本创建方式 1、 torch.tensor() 2、torch.Tensor() 3、torch.IntTensor() 等 创建线性张量和随机张量 1、创建线性张量 2、创建随机张量 切换设备 类型转换 与 Numpy 数据转换 1、张量转 Numpy 2、Numpy 转张量 tenso…

如何将FPGA设计的验证效率提升1000倍以上(4)

本文为系列文章的完结篇。用户应用设计中的信号&#xff0c;在经历编译器的多次迭代优化之后&#xff0c;在FPGA芯片内部运行时&#xff0c;可能已经被重新命名、“改头换面”或“机里机气”。要想以人工经验进行追踪&#xff0c;构建目标寄存器信号与RTL设计源码之间的映射关系…

Linux驱动11 --- buildroot杂项驱动开发方法

目录 一、Buildroot 1.1介绍 文件系统 1.一个完整的操作系统需要包含大量的文件 2.在嵌入式开发中目前应用最广泛的文件系统制作工具就是 buildroot&#xff0c;busybox 3.buildroot 制作文件系统&#xff08;了解&#xff09; 二、杂项驱动编程 1.1 驱动编程做的内容 2.2…

Unity物理系统由浅入深第三节:物理引擎底层原理剖析

Unity物理系统由浅入深第一节&#xff1a;Unity 物理系统基础与应用 Unity物理系统由浅入深第二节&#xff1a;物理系统高级特性与优化 Unity物理系统由浅入深第三节&#xff1a;物理引擎底层原理剖析 Unity物理系统由浅入深第四节&#xff1a;物理约束求解与稳定性 Unity 物理…

Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)脚步

1、Docker安装RocketMq 2、Docker安装Nginx 3、Docker安装MySql 4、Docker安装Minio 5、Docker安装jenkins 6、Docker安装Redis 1、Docker安装RocketMq #!/bin/bash# 定义变量 NAMESRV_CONTAINER"rocketmq-namesrv" BROKER_CONTAINER"rocketmq-broker&quo…

WPF学习笔记(27)科学计算器

科学计算器1. 前端界面2. 功能代码3. 效果展示1. 前端界面 <Window x:Class"Cal.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http:/…

【Linux系列】unzip file 命令

博客目录掌握 unzip -o 命令&#xff1a;高效解压并覆盖文件的完整指南一、unzip 命令基础二、-o 选项的核心作用三、典型应用场景四、与其他选项的组合使用五、注意事项与风险防范六、替代方案与高级技巧掌握 unzip -o 命令&#xff1a;高效解压并覆盖文件的完整指南 在日常的…

1965–2022年中国大陆高分辨率分部门用水数据集,包含:灌溉用水、工业制造用水、生活用水和火电冷却

1965–2022年中国大陆高分辨率部门用水数据集 高质量用水数据集对推进变化环境下的水资源研究至关重要。然而&#xff0c;现有中国用水数据通常按行政区划或流域汇总&#xff0c;时空分辨率不足&#xff0c;难以支撑人类用水模式及时空变化特征的精细化分析。为此&#xff0c;…