用const时应注意的一些地方

博客介绍了使用const的注意事项,包括函数返回值为const时不能作左值,const定义的int可开辟数组但常量数组元素不行,不同const指针的含义,类中const成员函数不能修改属性及修改方法,以及类中const类型不能定义数组而enum可以等内容。

        Const我们经常要用到,但有时不注意就会导致程序异常,而你还不知道怎么回事,一些是在用const要注意的:

1. 函数返回值为const时,返回的东西赋给一个类型相同的标示后其不能为左值;

2. 用const定义的int可用来开辟数组,但const定义的常量数组中的元素,不能用来定义数组。

3. const int *i; int const *i; int * const i; 前两个功能相同,说明I所指向的内容不变;最后一   个说明指针指向的地址不变,但内容可变。

4. 类中的const成员函数,定义为在原型后加const。常量函数不能修改类中的任何属性。但有两种方法可   以修改。

    1) {(yourclass *)this->member = values;}

    2) 将一个成员定义成mutable即可被常量函数修改。

5. 类中的常量const 类型的,不能在类中被用来定义数组。而enum {ONE=100; TWO=2};定义的ONE、TWO   却可以。通常的enum定义的置分配问题:enum A{ L=9, Z};此时Z的值为10。

 

<think>嗯,用户之前问过关于`constexpr`变量的介绍,现在他们想知道是否可以用`const`代替所有使用`constexpr`的地方。我需要先回顾两者的区别,然后分析它们的用场景是否允许替换。 首先,`constexpr`强调编译常量,必须在编译确定值,而`const`只是表示运行的常量性,可能延迟到运行初始化。比如,数组大小必须用`constexpr`,因为数组的大小需要在编译确定,而用`const`可能无法保证这一点,如果`const`变量在运行初始化的话就会报错。 接下来要考虑用户可能的误区,他们可能认为`const`和`constexpr`可以互换,但实际上并非如此。需要举例说明哪些情况下只能用`constexpr`,比如模板参数、数组大小、编译计算等。同也要指出哪些情况下两者都可以使用,比如简单的常量定义,但此`constexpr`更严格,可能更安全。 另外,用户可能不太清楚`constexpr`函数的作用,这部分需要简要提及,说明`constexpr`函数可以在编译计算,而普通函数不行,这也是`const`无法替代的。 还需要注意C++标准的版本差异,比如C++11和C++14对`constexpr`的不同支持,但用户的问题主要在于替换的可能性,可能不需要深入版本差异,但可以提到C++17对`constexpr`的扩展,比如支持`std::string`等。 最后要总结替换的条件,即当`const`变量的初始化表达式本身是编译常量,才能用`const`代替,但反之则不行。需要强调`constexpr`的不可替代性,特别是在需要编译确定的场景下。</think>在 C++ 中,**`constexpr` 和 `const` 的功能有部分重叠,但并非所有能用 `constexpr` 的地方都能用 `const` 完全替代**。它们的核心区别在于**初始化机**和**使用场景**。以下是具体分析: --- ### **1. 当 `const` 可以替代 `constexpr` ** **条件**: 如果 `const` 变量的初始化表达式本身是**编译常量**,且该变量仅用于**不需要严格编译计算**的场景,则可以用 `const` 替代 `constexpr`。 **示例**: ```cpp // 使用 constexpr constexpr int size = 10; int arr1[size]; // 合法 // 使用 const(如果初始值是编译确定的) const int size_const = 10; int arr2[size_const]; // 合法:size_const 是编译常量 ``` --- ### **2. 当 `const` 无法替代 `constexpr` ** #### **(1) 需要编译计算的场景** - **数组大小、模板参数**等必须使用编译常量的场景,只能用 `constexpr`: ```cpp constexpr int N = 10; int arr[N]; // 合法 const int M = 10; int arr[M]; // 合法(仅当 M 是编译常量) int x = 5; const int y = x; // y 是运行常量 int arr[y]; // 错误:y 的值在编译不确定 ``` #### **(2) 编译函数计算** `constexpr` 函数可以在编译计算结果,而普通函数(即使返回值是 `const`)无法做到: ```cpp constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n - 1); } constexpr int result = factorial(5); // 编译计算 120 // 若用 const 替代: int fact(int n) { /* 相同实现 */ } const int result = fact(5); // 运行计算,无法用于数组大小等场景 ``` #### **(3) 模板非类型参数** 模板的非类型参数(如整型、指针)必须使用编译常量: ```cpp template<int Size> class Array { /*...*/ }; constexpr int size = 10; Array<size> arr1; // 合法 const int size_const = 10; Array<size_const> arr2; // 合法(仅当 size_const 是编译常量) int x = 10; const int y = x; Array<y> arr3; // 错误:y 不是编译常量 ``` --- ### **3. 关键区别总结** | **场景** | `constexpr` | `const` | |------------------------|---------------------------|-----------------------------| | **初始化机** | **必须编译确定** | 可编译或运行确定 | | **数组大小/模板参数** | 支持 | 仅当初始值是编译常量支持 | | **函数返回值** | 可编译计算(`constexpr` 函数) | 只能是运行常量 | | **类型限制** | 仅限字面类型(C++11/14) | 无限制 | --- ### **4. 何可以互换?** 只有以下情况可以互换: - `const` 变量的初始化表达式本身是**编译常量**(如字面量、其他 `constexpr` 变量),且不涉及需要严格编译计算的场景。 **示例**: ```cpp constexpr int a = 10; const int b = a; // 合法:a 是编译常量 constexpr int c = b; // 合法:b 的值在编译已知 ``` --- ### **5. 何必须用 `constexpr`?** 以下场景必须使用 `constexpr`: 1. **模板非类型参数**: ```cpp template<int N> struct S {}; constexpr int size = 10; S<size> s; // 合法 ``` 2. **编译计算函数**: ```cpp constexpr int square(int x) { return x * x; } constexpr int val = square(5); // 编译计算 ``` 3. **需要强制编译初始化**: ```cpp constexpr int* p = nullptr; // 编译确定指针值 ``` --- ### **6. 总结** - **能用 `const` 替代 `constexpr` 的情况**: 当 `const` 变量本身是编译常量,且不涉及严格需要编译计算的场景(如模板参数、数组大小)。 - **必须用 `constexpr` 的情况**: 需要强制编译初始化、编译函数计算或模板参数传递。 **核心原则**: - `constexpr` 是更严格的 `const`,它保证了编译计算能力。 - `const` 仅保证“不可修改”,不保证“编译确定值”。 合理选择二者,可以兼顾代码的灵活性和性能!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值