c++常量和常量表达式

const,默认情况下仅在文件内有效

const int i(12);

const引用:对常量的引用不能被用作修改它所绑定的对象

const int ci(5);

const int &rci(ci);

rci = 90;//错误 不能修改

 

允许常量引用绑定到非常量的对象、字面值或表达式上

int i = 20;

const int &ri(20);

const int &ri3(i + ri);

 

常量引用仅对引用可参与的操作作出了限定,对于引用的对象本身未做限定

int i(10);

const int &c(i);

i = 90;//i不是常量,可以改变值

c = 20;//错误,c是一个常量引用,const限定了c为常量不能修改,i的修改与c的限定无关。

cout << c << endl;//值为90

 

//指针和const

int iv(10);

int iv1(23);

const int * pci1(&iv);//指向常量的指针,限定了该指针的操作,pci1的值可以改变,pcil指向的值不能变

pci1 = &iv1;

iv = 30;

int * const pci2(&iv);//常量指针,把指针本身定位常量,pci2的值不能改变,pci2指向的值可以改变

*pci2 = 90;

 

cout << *pci1 << endl;//23

cout << *pci2 << endl;//90

 

顶层和底层

顶层:表示指针本身是个常量

底层:指针所指的对象是常量

小技巧:const int * p: const修饰的是*p,也就是*p不能变。

        int * const p: const修饰的是p,也就是p不能变。

 

 

字面值和constexpr

常量表达式:字面值是常量表达式,用常量表达式初始化的const对象也是常量表达式

const int ci = 20;//ci是常量表达式

const int cii = ci + 90;//cii是常量表达式

int iv = 30;//iv不是常量表达式

 

声明为constexpr的变量一定是常量,而且必须用常量表达式初始化

constexpr int cif = 23;

 

constexpr声明的指针,只对指针有效,与指针指向的对象无关

constexpr int cvi(12);//必须定义到函数体外部才能被cip使用

constexpr const int * cip(&cvi);

cout << *cip << endl;

<think>我们正在讨论C++中的常量表达式。根据用户需求,需要解释常量表达式的定义、特点使用方法。结合之前提供的引用内容,我们可以总结如下: ### 定义 常量表达式constant expression)是指在编译期间就可以计算出结果的表达式。它的值在程序运行前就已确定,且不会改变。例如: - 字面量:`42`, `'a'`, `true` - 由常量表达式组成的运算:`20 * 4 + 8` - 用常量表达式初始化的`const`变量(在C++11之前)或`constexpr`变量(C++11起) ### 特点 1. **编译时计算**:值在编译阶段确定,不占用运行时资源。 2. **类型限制**:只能是字面类型(literal type),包括算术类型、引用、指针以及满足特定条件的类类型等。 3. **严格约束**: - 对于`constexpr`函数(C++11引入): - 函数体必须只包含一条`return`语句(C++14放宽此限制)。 - 所有参数返回值必须是字面类型。 - 函数体中不能有未初始化的变量、不能有`goto`或非字面类型的变量定义等(C++14起允许局部变量循环等)。 - 对于`constexpr`变量: - 必须由常量表达式初始化。 ### 使用方法 1. **定义常量**: ```cpp constexpr int size = 10; // 正确:字面量是常量表达式 constexpr double pi = 3.14159; // 正确 ``` 2. **定义数组大小**: ```cpp int arr[size]; // 正确:size是常量表达式 ``` 3. **模板非类型参数**: ```cpp template<int N> struct Array { int data[N]; }; Array<size> arr; // 正确 ``` 4. **`constexpr`函数**: ```cpp constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n-1); } constexpr int fact5 = factorial(5); // 编译时计算,结果为120 ``` 5. **条件编译(C++17起)**: ```cpp if constexpr (sizeof(int) == 4) { // 仅在int为4字节时编译此代码块 } ``` ### 注意事项 - **`const` vs `constexpr`**: - `const`只保证运行时不修改,但不一定是编译期常量(如`const int x = get_value();`)。 - `constexpr`强制编译期求值,是更严格的常量。 - **C++标准演进**: - C++11:引入`constexpr`,函数限制严格(单条`return`)。 - C++14:放宽`constexpr`函数限制,允许多条语句、局部变量、循环等。 - C++17:引入`if constexpr`。 ### 示例代码 ```cpp #include <iostream> // C++14起允许循环局部变量 constexpr int sum_to_n(int n) { int sum = 0; for (int i = 1; i <= n; ++i) { sum += i; } return sum; } int main() { constexpr int n = 10; constexpr int total = sum_to_n(n); // 编译时计算 std::cout << "Sum of 1 to " << n << " is " << total << std::endl; // C++17的if constexpr if constexpr (total > 50) { std::cout << "Large sum\n"; } else { std::cout << "Small sum\n"; } return 0; } ``` ### 判断常量表达式的方法 1. **使用`constexpr`声明**:编译器会在编译时检查是否满足常量表达式要求。 2. **静态断言(static_assert)**: ```cpp static_assert(sum_to_n(10) == 55, "Compile-time check"); ``` 如果`sum_to_n(10)`不是常量表达式或结果错误,编译失败。 > **要点总结**:常量表达式通过编译期计算提升性能,关键工具包括`constexpr`变量/函数`if constexpr`(C++17)。其核心价值在于将计算从运行时转移到编译时[^1][^2][^5]。 §§相关问题§§ 1. `constexpr`函数在C++11C++14标准中有何主要区别? 2. 如何在编译时检测一个表达式是否为常量表达式? 3. `if constexpr`普通`if`语句在性能上有何差异? 4. 常量表达式可以用于哪些标准库容器或算法中? </think> ### C++ 常量表达式详解 #### 1. **定义本质** 常量表达式constant expression)指**在编译期间就能计算出结果的表达式**,其值在程序运行前已确定且不可更改。核心特征: - 值必须是编译期可知的常量 - 可参编译期计算优化 - 类型必须是字面类型(literal type) ```cpp constexpr int size = 10; // √ 整数字面量 constexpr double pi = 3.14159; // √ 浮点字面量 constexpr char ch = 'A'; // √ 字符字面量 int x = 5; constexpr int invalid = x; // × 非常量初始化 ``` #### 2. **关键特性** | 特性 | 说明 | 示例 | |------|------|------| | **编译期计算** | 值在编译阶段确定 | `constexpr int area = 20*4+8;` | | **强约束性** | 严格限制表达式组成 | 只能包含字面量、常量、其他常量表达式 | | **类型限制** | 仅限字面类型 | 算术类型、引用、指针、特定类类型等 | | **函数要求** | `constexpr`函数需满足特定条件 | 详见表3 | **表:`constexpr`函数要求(C++11 vs C++14)** | 要求 | C++11标准 | C++14放宽 | |------|-----------|-----------| | 函数体 | 只能包含单条`return` | 允许多条语句 | | 局部变量 | 禁止 | 允许(但需常量初始化) | | 控制流 | 禁止循环/条件 | 允许`for`/`if` | | 返回类型 | 必须返回字面类型 | 同左 | | 前置要求 | 使用前必须定义 | 同左 | #### 3. **核心用途** 1. **数组维度定义** ```cpp constexpr int N = 100; int arr[N]; // 合法:编译期确定数组大小 ``` 2. **模板非类型参数** ```cpp template<int Size> struct Buffer { /*...*/ }; Buffer<sizeof(int)*8> buf; // 使用常量表达式实例化 ``` 3. **编译时计算优化** ```cpp constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n-1); } int arr[factorial(5)]; // 120元素数组,编译期计算 ``` 4. **条件编译(C++17)** ```cpp if constexpr (sizeof(void*) == 8) { // 64位平台专用代码 } else { // 32位平台代码 } ``` #### 4. **判断常量表达式的方法** 1. **使用`constexpr`声明** ```cpp constexpr auto val = expression; // 编译失败则非常量 ``` 2. **静态断言检测** ```cpp static_assert(expression, "Error"); // 编译期检查 ``` 3. **模板参数验证** ```cpp template<int V> struct Test {}; Test<expression> t; // 只接受常量表达式 ``` #### 5. **典型错误示例** ```cpp constexpr int f() { int x = 1; // √ C++14允许局部变量 // return rand(); // × 禁止调用非constexpr函数 return x + 5; } void test() { int d = 10; // constexpr int e = d; // × d不是常量 constexpr int e = f(); // √ } ``` #### 6. **最佳实践建议** 1. 优先用`constexpr`替代`const`声明编译期常量 2. 对数学计算、查找表等使用`constexpr`函数 3. 在模板元编程中充分利用编译期计算 4. C++17+项目使用`if constexpr`简化条件编译 > **核心价值**:常量表达式将计算从运行时转移到编译时,提升性能并增强类型安全。尤其在资源受限系统模板元编程中发挥关键作用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值