在 C++ 中,const 和 constexpr 是两个关键字,它们分别用于定义常量,但它们的使用场景和作用有所不同。理解它们的区别和联系对于编写高效和可靠的代码至关重要。
1. const 关键字
1.1 基本概念
const 关键字用于声明常量。被声明为 const 的变量在其整个生命周期中不能被修改。
1.2 用法示例
const int x = 5;
x = 10; // 错误:x 是只读变量
1.3 特点
- 编译期检查:编译器会在编译时检查
const变量的赋值操作,确保它们不会被修改。 - 可以用于指针和引用:
const还可以用来修饰指针和引用,表示指向的值不能修改。
const int *ptr = &x; // 指向 const int 的指针
int const *ptr2 = &x; // 同上,另一种写法
int *const ptr3 = &x; // const 指针,指针本身不可变
const int &ref = x; // 指向 const int 的引用
1.4 函数中的 const
在函数中,const 可以修饰函数参数和成员函数。
- 修饰参数:表示参数在函数内部不可修改。
- 修饰成员函数:表示成员函数不会修改类的成员变量。
void func(const int a) {
// a 不能被修改
}
class MyClass {
public:
int getValue() const {
return value; // 这个成员函数不会修改任何成员变量
}
private:
int value;
};
2. constexpr 关键字
2.1 基本概念
constexpr 关键字用于声明常量表达式。与 const 不同,constexpr 保证表达式在编译时求值。这意味着 constexpr 变量不仅是不可变的,而且其值在编译时就已经确定。
2.2 用法示例
constexpr int x = 5;
constexpr int y = x + 5; // 编译时求值
2.3 特点
- 编译期常量:
constexpr保证变量在编译时就能求值,从而可以用于数组大小、模板参数等需要编译时常量的地方。 - 可以用于函数:
constexpr函数的返回值在编译时求值,如果参数也是常量表达式。
constexpr int square(int x) {
return x * x;
}
constexpr int y = square(5); // 编译时求值
2.4 与 const 的区别
- 编译时求值:
constexpr强制在编译时求值,而const只是在运行时不可修改。 - 应用场景:
constexpr更适用于需要在编译时确定值的场景,如模板参数、数组大小等,而const更适用于需要不可变但不要求编译时确定的场景。
3. const 和 constexpr 的联系
尽管 const 和 constexpr 有显著的区别,但它们也有一些联系:
- 不可变性:两者都可以用于定义不可变的变量。
- 互补性:在实际编程中,
const和constexpr常常互补使用。例如,可以使用constexpr定义编译时常量,然后用const修饰函数参数来保证参数不可修改。
constexpr int size = 10;
const int arr[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
4. 实际编程中的应用
4.1 数组大小
使用 constexpr 可以定义数组的大小,使得数组大小在编译时确定。
constexpr int size = 10;
int arr[size];
4.2 模板参数
模板参数需要编译时常量,constexpr 非常适合用于此场景。
template<int N>
struct MyArray {
int data[N];
};
constexpr int size = 10;
MyArray<size> arr;
4.3 常量表达式函数
constexpr 函数可以在编译时求值,提高代码的执行效率。
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int result = factorial(5); // 编译时计算
5. 结论
const 和 constexpr 是 C++ 中两个重要的关键字,它们分别用于定义常量,但各自有不同的应用场景和特点。const 用于声明在运行时不可修改的变量,而 constexpr 用于声明在编译时即可求值的常量表达式。理解和正确使用这两个关键字,可以使代码更安全、高效和易于维护。









