区分C++常量表达式、const、constexpr

1. 前言

在C++中,我们经常会使用常量或者表达式,而其中涉及到的常量包括了const和constexpr。但是,要清楚它们之间的区别却并不容易,所以在这篇文章中,我们将重点讨论C++中的常量表达式、const和constexpr的区别。

2. C++常量表达式

2.1 常量表达式的定义

C++11引入了常量表达式(constant expression)的概念,它用于表示在编译期间可以被求值的表达式。在C++中,常量表达式的定义并不是很明确,一般地认为一个表达式属于常量表达式需要满足以下条件:

它只包含了编译期间能够处理的操作符和函数

在表达式求值时,其结果必须在编译期间就可以求得

它的类型必须属于整数类型、枚举类型、浮点类型、指针类型或引用类型

下面举几个常量表达式的例子:

constexpr int n1 = 10;

constexpr int n2 = n1 * 2;

enum class Color { RED, BLUE, GREEN };

constexpr Color c = Color::RED;

constexpr double pi = 3.1415926;

constexpr int* p = nullptr;

int arr[n1]; // 正确

int arr2[n2]; // 正确

Color arr3[c]; // 正确

int arr4[pi * 10]; // 错误

2.2 常量表达式的优点

常量表达式的存在使得编译器在编译期间就可以确定某个变量的值,这在程序的优化和性能方面有着非常重要的意义。例如在下面的代码中:

const int n = 100;

int arr[n];

虽然我们将n定义为了const常量,但是在定义数组时,编译器并不能确定n的值,因此需要在运行期间分配内存。但是,如果我们将n定义为常量表达式的形式,编译器就可以在编译期间就知道数组大小,从而在程序执行时不需要再进行内存分配操作,从而提高程序的运行效率。

3. const关键字

3.1 const的作用

在C++中,const关键字可以用来声明一个常量,即变量的值不能被改变:

const int n = 100;

n = 200; // 错误

const还可以修饰函数的参数和返回值,用于限定参数和返回值的只读属性。例如:

int add(const int& a, const int& b) {

return a + b;

}

const int sum = add(1, 2);

在上面的例子中,我们用const修饰了函数的参数,表示在函数内部不会改变参数的值。同时,我们也将函数的返回值声明为const,表示函数返回的值不能被修改。

3.2 const并非常量表达式

虽然const可以用来声明一个常量,但是const并不等同于常量表达式。const定义的常量虽然不能被修改,但是在编译期间并不能确定它的值,因此不能用来定义数组的大小等需要确定值的场合。例如:

const int n = 100;

int arr[n]; // 错误

上面的例子中,我们将n定义为了const常量,但是在定义数组时,编译器并不能确定n的值,因此需要在运行期间分配内存。

4. constexpr关键字

4.1 constexpr的作用

C++11引入了constexpr关键字,用于声明常量表达式。constexpr声明的变量可以被视为编译期间就可以被确定的常量,因此可以用在需要确定值的场合,例如定义数组的大小等。

constexpr int n = 100;

int arr[n]; // 正确

4.2 constexpr函数

除了用来声明常量表达式外,constexpr还可以用来修饰函数,表示该函数返回的值是常量表达式。常量表达式函数可以在编译期间就被计算出来,因此可以用来定义constexpr变量、数组的大小等。例如:

constexpr int fib(int n) {

return n <= 1 ? n : fib(n - 1) + fib(n - 2);

}

constexpr int f = fib(10); // 在编译期间计算fib(10)的值

int arr[f]; // 正确

需要注意的是,constexpr函数的参数和返回值必须都是常量表达式类型。因此,下面的例子是错误的:

int add(const int& a, const int& b) {

return a + b;

}

constexpr int sum = add(1, 2); // 错误

由于add函数的参数不是常量表达式类型,因此不能在编译期间就计算出sum的值。

5. 总结

C++中的常量表达式、const和constexpr虽然都与常量有关,但是它们之间的区别还是很大的。常量表达式用于定义编译期间可以被求值的表达式,可以用来定义constexpr变量、数组的大小等。const关键字可以用来声明常量,但是不能用于定义数组的大小等需要确定值的场合。constexpr关键字除了用于声明常量表达式外,还可以用于修饰函数,表示函数返回的值是常量表达式。

后端开发标签