C++11 constexpr
外观
C++11 constexpr[编辑 | 编辑源代码]
constexpr是C++11引入的关键字,用于声明编译时常量表达式(compile-time constant expression)。它允许在编译期计算表达式的值,从而优化性能并增强类型安全性。
核心概念[编辑 | 编辑源代码]
基本定义[编辑 | 编辑源代码]
constexpr可修饰:
- 变量:声明该变量必须是编译期常量
- 函数:声明该函数在给定编译期常量参数时可产生编译期常量结果
与const的区别[编辑 | 编辑源代码]
特性 | const | constexpr |
---|---|---|
初始化时机 | 运行期或编译期 | 必须在编译期确定 |
修饰函数 | 不能保证编译期求值 | 可编译期求值 |
数组大小 | C++98中不可用 | 可用作数组维度 |
语法规范[编辑 | 编辑源代码]
变量声明[编辑 | 编辑源代码]
constexpr int max_size = 100; // 正确:字面量初始化
constexpr double pi = 3.14159; // 正确:浮点字面量
函数声明[编辑 | 编辑源代码]
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
代码示例[编辑 | 编辑源代码]
基础示例[编辑 | 编辑源代码]
计算编译期阶乘:
#include <iostream>
constexpr int compute_factorial(int n) {
return (n <= 1) ? 1 : (n * compute_factorial(n - 1));
}
int main() {
constexpr int val = compute_factorial(5); // 编译期计算
int dynamic_val = compute_factorial(5); // 运行期计算
std::cout << "Compile-time: " << val
<< "\nRuntime: " << dynamic_val;
}
进阶应用[编辑 | 编辑源代码]
编译期字符串哈希:
constexpr unsigned int hash_str(const char* s, int off = 0) {
return !s[off] ? 5381 : (hash_str(s, off+1) * 33) ^ s[off];
}
int main() {
constexpr auto hash = hash_str("hello");
static_assert(hash == 2107146360, "Hash mismatch");
}
限制条件[编辑 | 编辑源代码]
constexpr函数在C++11中需满足:
- 函数体必须只有单个return语句(递归除外)
- 不能包含:
* 循环语句 * goto语句 * 非字面类型的变量 * 未初始化的变量
实际应用案例[编辑 | 编辑源代码]
案例1:固定尺寸数组[编辑 | 编辑源代码]
constexpr int get_array_size() { return 32; }
int main() {
int arr[get_array_size()]; // 合法数组声明
}
案例2:模板元编程[编辑 | 编辑源代码]
结合模板实现编译期计算:
template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N-1>::value;
};
template<>
struct Factorial<0> {
static constexpr int value = 1;
};
int main() {
static_assert(Factorial<5>::value == 120, "");
}
版本演进[编辑 | 编辑源代码]
标准 | 改进 |
---|---|
C++11 | 基础功能 |
C++14 | 放宽函数限制(允许多语句、局部变量等) |
C++17 | 支持if constexpr |
C++20 | 支持虚函数、try-catch等 |
性能分析[编辑 | 编辑源代码]
数学公式示例(欧拉公式验证): 在编译期验证:
#include <complex>
#include <iostream>
constexpr bool verify_euler() {
using namespace std::complex_literals;
constexpr std::complex<double> res = std::exp(1.0i * 3.1415926535);
return (std::abs(res.real() + 1) < 1e-9) &&
(std::abs(res.imag()) < 1e-9);
}
static_assert(verify_euler(), "Euler's formula failed");
最佳实践[编辑 | 编辑源代码]
- 优先用constexpr替代宏常量
- 对数学计算、查找表等使用constexpr
- 注意C++11的限制条件
- 利用static_assert进行编译期验证
页面模块:Message box/ambox.css没有内容。
过度使用constexpr可能导致编译时间显著增加 |