所谓常量表达式,指的就是由多个(≥1
)常量 组成的表达式。
- 如果表达式中的成员都是常量,那么该表达式就是一个常量表达式。
- 常量表达式一旦确定,其值将无法修改。
// 1)
int url[10];//正确
// 2)
int url[6 + 4];//正确
// 3)
int length = 6;
int url[length];//错误,length是变量
非常量表达式只能在程序运行阶段计算出结果;而常量表达式的计算往往发生在程序的编译阶段。
常量表达式的计算往往发生在程序的编译阶段,这可以极大提高程序的执行效率,因为表达式只需要在编译阶段计算一次,节省了每次程序运行时都需要计算一次的时间。
constexpr 关键字的功能是 使指定的常量表达式获得在程序编译阶段计算出结果的能力,而不必等到程序运行阶段。
- constexpr可以用于修饰变量、函数(包括模板函数)以及类的构造函数。
- 注意,获得在编译阶段计算出结果的能力,并不代表 constexpr 修饰的表达式一定会在程序编译阶段被执行,具体的计算时机还是编译器说了算。
constexpr修饰普通变量
使用 constexpr 修改普通变量时,变量必须经过初始化且 初始值必须是一个常量表达式。
int main()
{
constexpr int num = 1+2+3; //num经过初始化、初始值也是常量表达式
int url[num] = {1,2,3,4,5,6}; //num如果不定义为constexpr,编译器会报错。
return 0;
}
- 这里constexper用const代替也行。
- 但const 和 constexpr 并不相同。
constexpr修饰函数
constexpr 还可以用于修饰函数的返回值,这样的函数又称为“常量表达式函数”。
constexpr 并非可以修改任意函数的返回值。换句话说,一个函数要想成为常量表达式函数,必须满足如下 4 个条件:
-
1) 整个函数的函数体中,除了可以包含 using 指令、typedef 语句以及 static_assert 断言外,只能包含一条 return 返回语句。
constexpr int display(int x) { //可以添加 using 执行、typedef 语句以及 static_assert 断言 return 1 + 2 + x; }
-
2)该函数必须有返回值,即函数的返回值类型不能是 void。
constexpr void display() { //返回值类型为 void 的函数,不属于常量表达式函数。 //函数体 }
-
3)函数在使用之前,必须有对应的定义语句。
-
普通的函数调用只需要提前写好该函数的声明部分即可(函数的定义部分可以放在调用位置之后甚至其它文件中),但常量表达式函数在使用前,必须要有该函数的定义。
-
#include <iostream> using namespace std; //普通函数的声明 int noconst_dis(int x); //常量表达式函数的声明 constexpr int display(int x); //常量表达式函数的定义 constexpr int display(int x){ return 1 + 2 + x; } int main() { //调用常量表达式函数 int a[display(3)] = { 1,2,3,4 }; cout << a[2] << endl; //调用普通函数 cout << noconst_dis(3) << endl; return 0; } //普通函数的定义 int noconst_dis(int x) { return 1 + 2 + x; }
-
-
4) return 返回的表达式必须是常量表达式。
#include <iostream> using namespace std; int num = 3; constexpr int display(int x){ return num + x; // num + x 不是常量表达式,编译器会报错 } int main() { //调用常量表达式函数 int a[display(3)] = { 1,2,3,4 }; return 0; }
constexpr修饰类的构造函数
constexpr可以修饰C++ 内置类型的数据。但不能修饰自定义的数据类型。
-
1) 修饰构造函数
struct myType{ constexpr myType(char* name, int age):name(name),age(age){}; //要求该构造函数的函数体必须为空, //且采用初始化列表的方式为各个成员赋值时,必须使用常量表达式。 }
-
2)修饰成员函数
- 类中的成员函数必须满足前面提到的 4 个条件。
constexpr修饰模板函数
C++11 标准规定,如果 constexpr 修饰的模板函数实例化结果不满足常量表达式函数的要求,则 constexpr 会被自动忽略,即该函数就等同于一个普通函数。