constexpr 是 C++11 引入的关键字,用于在编译期进行常量表达式计算,从而提高程序性能和安全性。以下是其核心作用和用法:
一.作用
1编译期
计算 constexpr 变量或函数的值在编译时确定,避免运行时计算开销。例如,数组大小、模板参数等需要在编译期确定的场景。
2 类型安全
相比宏(#define),constexpr 提供类型检查,避免宏替换带来的潜在错误。
3代码优化
编译器可以在编译期优化 constexpr 相关的计算,减少运行时负担。
4支持模板元编程
constexpr 函数可用于生成编译时常量,简化模板元编程逻辑。
二. 用法
1. 定义常量表达式变量
constexpr int MAX_SIZE = 100; // 编译时常量
int arr[MAX_SIZE]; // 合法,MAX_SIZE 在编译期已知
2. 定义常量表达式函数
要求:函数体只能包含返回语句或静态断言,参数和返回值必须是字面类型(如基本类型、枚举、指针等)。
constexpr int square(int x) {
return x * x;
}
int main() {
constexpr int val = square(10); // 编译期计算,val = 100
int arr[val]; // 合法
}
3. 定义常量表达式构造函数(C++11 起)
要求:构造函数体只能包含简单的初始化逻辑。
struct Point {
int x, y;
constexpr Point(int x, int y) : x(x), y(y) {}
};
constexpr Point p(1, 2); // p 在编译期构造
4. C++14 及更高版本的扩展
更复杂的逻辑:constexpr 函数可以包含局部变量、循环、条件语句等。
constexpr int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
constexpr int fact_5 = factorial(5); // 编译期计算,fact_5 = 120
5. 用于模板参数
template <int N>
void printArraySize() {
std::cout << "Array size: " << N << std::endl;
}
constexpr int size = 10;
printArraySize<size>(); // 输出:Array size: 10
注意事项
constexpr 变量必须初始化
且初始值必须是常量表达式。
constexpr 函数的参数和返回值必须是字面类型
不能是动态分配的对象或包含运行时行为的类型。
与 const 的区别
const:仅表示值不可修改,但可以在运行时初始化。
constexpr:要求值必须在编译期确定,且必须是常量表达式。
总结
constexpr 是 C++ 中用于编译期计算的关键特性,适用于需要编译期常量的场景(如数组大小、模板参数等)。通过合理使用 constexpr,可以提高程序性能、增强类型安全,并简化模板元编程逻辑。
三.const 与constexpr 区别
const
表示“不可修改”,适用于运行时逻辑,防止意外修改对象或变量。
constexpr
表示“编译期常量”,适用于需要编译期优化的场景(如数组大小、模板参数),要求值必须在编译期确定。
1. 初始化时间
const
const 变量可以在运行时初始化,其值在初始化后不可修改。例如:
int main() {
const int x = getInput(); // 运行时初始化(合法)
x = 10; // 错误:const 变量不可修改
}
constexpr
constexpr 变量必须在编译期初始化,其值必须是常量表达式。例如:
constexpr int y = 10; // 编译期初始化(合法)
constexpr int z = getInput(); // 错误:getInput() 不是编译期常量
2. 函数和变量
const 函数
const 用于成员函数,表示函数不会修改对象的状态:
class MyClass {
public:
int getValue() const { return value_; } // 不会修改对象
private:
int value_;
};
constexpr 函数
constexpr 函数必须在编译期可计算,且其返回值是常量表达式:
constexpr int square(int x) { return x * x; }
int main() {
constexpr int val = square(5); // 编译期计算(合法)
}
3. 构造函数
const 对象
const 对象必须在初始化时赋值,且不能修改:
const int a = 10; // 合法
a = 20; // 错误:const 对象不可修改
constexpr 构造函数
constexpr 构造函数用于构造编译期常量对象,其初始化列表和函数体必须满足 constexpr
struct Point {
int x, y;
constexpr Point(int x, int y) : x(x), y(y) {}
};
constexpr Point p(1, 2); // p 在编译期构造
4. 使用场景
const
适用于需要防止意外修改的场景,例如:
函数参数(防止修改):
void print(const std::string& str) { /* ... */ }
成员变量(防止修改):
class MyClass {
public:
const int id_; // 初始化后不可修改
MyClass(int id) : id_(id) {}
};
constexpr
适用于需要编译期常量的场景,例如:
数组大小:
constexpr int SIZE = 100;
int arr[SIZE]; // 合法,SIZE 在编译期已知
模板参数:
template <int N>
void printArraySize() {
std::cout << "Array size: " << N << std::endl;
}
constexpr int size = 10;
printArraySize<size>(); // 输出:Array size: 10