本文共 1570 字,大约阅读时间需要 5 分钟。
constexpr是C++11开始提出的关键字,其意义与14版本有一些区别。
C++11中的constexpr指定的函数返回值和参数必须是字面值,而且必须有且只有一行return代码,这给函数的设计者带来了更多的限制。而C++14中只要保证返回值和参数是字面值就行了,函数体中可以加入更多的语句,方便了更灵活的计算。很多人都把constexpr和const相比较。其实,const并不能代表“常量”,它仅仅是对变量的一个修饰,告诉编译器这个变量只能被初始化,且不能被直接修改(实际上可以通过堆栈溢出等方式修改)。而这个变量的值,可以在运行时,也可以在编译时指定。constexpr可以用来修饰变量、函数、构造函数。一旦以上任何元素被constexpr修饰,那么等于说是告诉编译器 “请大胆地将我看成编译时就能得出常量值的表达式去优化我”。
constexpr所修饰的变量一定是编译期可求值的,所修饰的函数在其所有参数都是constexpr时,一定会返回constexpr。
constexpr int foo( int i) { return i + 5; } int main() { constexpr int a = foo(1); // ok constexpr int b = foo(cin.get()); // !error constexpr int c = a * 2 + 1; // ok }
以下编译失败,对于funcTest,胆小的编译器并没有足够的胆量去做编译期优化,哪怕函数体就一句return 字面值;
const int funcTest() { return 10; } int main() { int arr[funcTest()];}//error : 函数调用在常量表达式中必须具有常量值
修改后,编译通过,编译期大胆地将funcTest()做了优化,在编译期就确定了func计算出的值10而无需等到运行时再去计算。
constexpr int funcTest() { return 10; } int main() { int arr[funcTest()];}
另一个例子
templateclass C {}; constexpr int FivePlus(int x) { return 5 + x; } void f(const int x) { C c1; // Error: x is not compile-time evaluable. C c2; // OK }
constexpr还能用于修饰类的构造函数,即保证如果提供给该构造函数的参数都是constexpr,那么产生的对象中的所有成员都会是constexpr,该对象也就是constexpr对象了,可用于各种只能使用constexpr的场合。注意,constexpr构造函数必须有一个空的函数体,即所有成员变量的初始化都放到初始化列表中。
struct A { constexpr A(int xx, int yy) : x(xx), y(yy) {} int x, y; }; constexpr A a(1, 2); enum { SIZE_X = a.x, SIZE_Y = a.y };
参考:
转载地址:http://ljiii.baihongyu.com/