C++11新特性之——constexpr
constexpr 用于声明编译时常量或编译时计算的函数。
用它修饰的变量或者函数,可以在编译阶段计算出结果,而不是在运行时,既保证了常量的正确性,又提升了程序效率。
简单地说,就是,constexpr是 C++11 给 “编译期” 加的 “计算权限”—— 让变量 或者 函数能在编译时 “干活”,而不是等程序run起来才开始。
一、修饰变量:强制 “编译期常量”
替代了传统的const的模糊常量性(即const可能是运行时常量,比如const int a = rand() ),constexpr变量必须在编译期间确定值,否则在编译时会报错。
示例:
constexpr int MaxNum = 100; // 编译期确定,可用于数组大小、模板参数等
int arr[MaxNum]; // 合法,因为MaxNum是编译期常量
const int b = 20; // 是常量,但本质是“运行时初始化后不可改”
constexpr int c = b; // 合法(b值编译期可知)
// 但如果 b=rand(),则c编译报错
二、修饰函数:“可编译期执行” 的函数
满足条件的constexpr函数,既可以像普通函数在运行时调用,也能在编译期被 “计算出结果”(比如给constexpr变量赋值时)。
限制条件(C++11标准):
① 函数体仅只有一条return语句(没有循环、分支等复炸逻辑)
② 参数和返回值必须是字面类型(如int、double、指针等,无自定义类对象)
示例:
// 编译期/运行:计算平方
constexpr int square(int x) {
return x * x;
}
// 编译期计算,结果25
constexpr int a = square(5);
// 运行时调用,和普通函数一样
int b = square(rand());
三、与const的区别
C++11中constexpr和const的核心区别是常量的确定时机 :const是 运行时不可更改,constexpr是编译期间必须确定。前者是只读,后者是编译期常量。
(这个差异也导致了constexpr通常比const高效,因为constexpr强制编译期计算,直接规避了运行时的开销,而const仅保证了 “只读”,值可能仍需运行时确定。)
1、修饰变量:核心差异在值的确定时机
const变量:仅保证修饰变量的值 “初始化后不可修改”,但值的确定时机可以是运行时(只要初始化后不变)
例:const int a = rand(); (rand()在运行时生成值,a 初始化后只读),但 a 不是 “编译期常量”,不能用于数组大小、模板参数。
constexpr变量:强制 “值在编译期确定”,否则编译报错。
例:constexpr int c = rand(); 编译报错(因为rand () 运行时才知道结果,无法满足编译期确定要求)。并且constexpr变量天然具备 “只读” 属性,可以说是比const更严格的 “常量”。
2. 修饰函数:constexpr有 “编译期执行” 能力,而const没有
const函数(非成员函数中,const仅能修饰成员函数,表示 “不修改对象状态”):无没有“编译期计算” 能力,只能在运行时调用。例如:const int add(int x, int y) { return x+y; }
(注:非成员函数加const在 C++ 中不合法,仅类的成员函数可以使用const修饰 “不修改对象”)。
constexpr函数:满足限制条件时,既能在编译期计算结果(给constexpr变量赋值时),也能在运行时调用(像普通函数)。例:constexpr int square(int x) { return x*x; }
一句话总结它们的区别:
const是 “运行时只读的变量 / 不修改对象的函数”,constexpr是 “编译期必须确定的变量 / 能编译期执行的函数”。
四、constexpr的使用场景
constexpr的核心优势是编译期计算,适合用于 “值 或者 逻辑 可在编译阶段确定” 的场景,具体可分为 3 类:
1、定义编译期常量
需在编译时确定值、且后续不可改的场景,如:
①数组大小(C++ 中数组大小需编译期常量)
②模板参数(模板实例化依赖编译期确定的参数)
③枚举值、数学常量(如圆周率)
示例:
constexpr int MAX_SIZE = 10;
int arr[MAX_SIZE]; // 合法,编译期确定数组大小
template<int N>
void printSize() { std::cout << N; }
printSize<MAX_SIZE>(); // 模板参数需编译期常量,constexpr适用
2、实现“编译期可计算”的简单逻辑
函数逻辑简单(如纯计算、无复杂分支 / 循环),且需要在编译期得到结果的场景,如:
①简单数学运算(平方、阶乘、数值转换)
示例:
// 编译期计算阶乘
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n-1);
}
constexpr int res = factorial(5); // 编译期算得120,运行时无开销
3、优化“运行时没有必要的计算”的场景
即使逻辑可在运行时执行,但用constexpr将计算提前到编译期,能减少运行时开销,如:
①固定配置的计算(如根据固定参数生成配置值)
②循环等待中的常量条件(编译期确定循环终止条件的基础值)
示例:
// 编译期计算确定固定配置的阈值,运行时直接使用
constexpr int MAX_SIZE = 1024 * 2;
while (value < MAX_SIZE) {
// 运行时不需要计算MAX_SIZE,直接用编译期得到的结果
}
五、小结
①效率提升:编译期计算避免运行时开销(比如常量计算、简单逻辑提前计算好);
②语法严谨:强制区分了“编译期常量” 和 “运行时常量”,减少因const模糊性导致的错误;
③支持元编程:为编译期逻辑(如模板参数、数组大小)提供合法的 “计算工具”。
更多推荐



所有评论(0)