【C/C++】const关键词及拓展
✅ C++ 中的 const
关键字 学习笔记
💡 关键词:常量、编译时常量、性能优化、安全性、C++11/C++14/C++17/C++20 特性
🧠 一、const
—— 常量修饰符
1.1 定义
const
是 “constant” 的缩写。- 表示一个变量一旦被初始化,其值就不能再改变。
1.2 基本用法
const int max_value = 100;
max_value = 200; // ❌ 编译错误
1.3 const
修饰指针
写法 | 含义 |
---|---|
const int* p 或 int const* p | 指向的内容不可变 |
int* const p | 指针本身不可变 |
const int* const p | 指针和内容都不可变 |
int a = 5, b = 10;const int* p1 = &a;
p1 = &b; // ✅ OK:可以修改指针指向
// *p1 = 20; // ❌ 错误:不能修改指向的内容int* const p2 = &a;
*p2 = 15; // ✅ OK:可以修改指向的内容
// p2 = &b; // ❌ 错误:不能修改指针指向const int* const p3 = &a;
// *p3 = 20; // ❌ 错误
// p3 = &b; // ❌ 错误
1.4 成员函数后加 const
表示该成员函数不会修改类的成员变量。
class Rectangle {
public:Rectangle(int w, int h) : width(w), height(h) {}int area() const {return width * height;}private:int width, height;
};
⚠️ 注意:非
const
函数不能在const
对象上调用。
🔥 二、constexpr
—— 编译期常量表达式
2.1 定义
- 表示这个变量或函数的结果可以在编译时求值,并且结果是一个常量。
2.2 基本用法
constexpr int square(int x) {return x * x;
}constexpr int s = square(5); // ✅ 编译时计算成 25
char buffer[s]; // ✅ 合法,数组大小为 25
2.3 constexpr
变量
constexpr double pi = 3.141592653589793;
- 必须在编译时就能确定值。
- 可用于数组大小、模板参数等需要常量表达式的场合。
2.4 constexpr
函数
constexpr int factorial(int n) {int result = 1;for (int i = 2; i <= n; ++i)result *= i;return result;
}
- C++14 起支持复杂逻辑(如循环、条件判断)。
2.5 if constexpr
(C++17)
template <typename T>
void foo(T t) {if constexpr (std::is_integral_v<T>) {// 编译时选择路径} else {// 其他处理方式}
}
⚡ 三、consteval
—— 立即函数(Immediate Function)
3.1 定义
consteval
是 C++20 新增的关键字。- 表示这个函数必须在编译期求值,否则会报错!
3.2 示例
consteval int sqr(int x) {return x * x;
}int main() {constexpr int a = sqr(5); // ✅ OK:编译时求值int b = 5;int c = sqr(b); // ❌ 错误:b 是运行时变量
}
🛠️ 四、constinit
—— 静态初始化保证
4.1 定义
constinit
是 C++20 新增的关键字。- 用于确保变量具有静态初始化(不是运行时动态初始化),避免不确定性行为。
4.2 示例
constinit int val = 100; // ✅ OK:静态初始化
int get_value() {return 42;
}constinit int value = get_value(); // ❌ 错误:get_value() 不是常量表达式
📊 五、四个关键字对比表
特性 | const | constexpr | consteval | constinit |
---|---|---|---|---|
是否修饰变量 | ✅ | ✅ | ❌(仅函数) | ✅ |
是否修饰函数 | ❌ | ✅ | ✅ | ❌ |
是否必须编译时求值? | ❌ | 否(推荐) | ✅ | 否(但必须是常量表达式) |
是否影响运行时性能? | 否 | 是(提前计算) | 是(强制编译期) | 否(但提升可预测性) |
是否可用于数组大小、模板参数? | 否 | ✅ | ✅ | ✅ |
是否能用于 if 条件分支? | ❌ | ✅ | ✅ | ❌ |
🧩 六、推荐实践
场景 | 推荐使用 |
---|---|
定义数学常量 | ✅ constexpr |
定义配置参数 | ✅ const 或 constexpr |
强制编译期计算 | ✅ consteval |
保证静态初始化 | ✅ constinit |
函数参数传入只读数据 | ✅ const 引用 |
数组大小、模板参数 | ✅ constexpr |
📝 七、总结一句话
const
是“我不会改这个值”constexpr
是“这个值编译时就确定了”consteval
是“你必须在编译时算出来”constinit
是“我要在程序启动时就准备好”
📘 示例汇总
// const 基础
const int a = 10;// constexpr 基础
constexpr int b = 10;
constexpr int c = b * 2; // ✅ OK// constexpr 函数
constexpr int add(int x, int y) {return x + y;
}constexpr int d = add(3, 4); // ✅ 编译时计算成 7// consteval 函数
consteval int cube(int x) {return x * x * x;
}constexpr int e = cube(3); // ✅ OK
int f = 3;
cube(f); // ❌ 错误:f 是运行时变量// constinit 变量
constinit int global_val = 100; // ✅ OK
constinit int another_val = add(2, 3); // ✅ OK