
本文共 2274 字,大约阅读时间需要 7 分钟。
基本含义和语法
这两个关键字都可以在对象声明和函数中使用。应用于对象的基本区别是:
const
声明一个对象为常量。这意味着一个保证,一旦初始化,该对象的值不会改变,编译器可以利用这个事实进行优化。它还有助于防止程序员编写修改初始化后不打算修改的对象的代码。constexpr
声明一个对象适合在Standard调用常量表达式中使用。但请注意,这constexpr
不是唯一的方法。
应用于功能的基本区别是:
const
只能用于非静态成员函数,而不能用于一般函数。它保证了成员函数不会修改任何非静态数据成员。constexpr
可以与成员和非成员函数以及构造函数一起使用。它声明了适用于常量表达式的函数。如果函数符合某些标准(7.1.5 / 3,4),编译器将只接受它,最重要的是(†):- 函数体必须是非虚拟的,非常简单:除typedef和静态断言之外,只
return
允许一个语句。在构造函数的情况下,只允许初始化列表typedefs和静态声明。(= default
和= delete
也被允许使用,但。) - 参数和返回类型必须是文字类型(即一般来说,非常简单的类型,通常是标量或集合)
- 函数体必须是非虚拟的,非常简单:除typedef和静态断言之外,只
常量表达式
如上所述,constexpr
声明两个对象以及适合在常量表达式中使用的函数。一个恒定的表达不仅仅是不变的:
- 它可用于需要编译时评估的地方,例如模板参数和数组大小说明符:
template<int N> class fixed_size_list { /*...*/ };
fixed_size_list<X> mylist; // X must be an integer constant expression
int numbers[X]; // X must be an integer constant expression
- 但请注意:
- 声明一些东西
constexpr
并不一定保证在编译时会被评估。它可以用于此类,但也可以在运行时评估的其他地方使用。 - 一个对象可能适合在常量表达式中使用,而不需要声明
constexpr
。例:int main() { const int N = 3; int numbers[N] = {1, 2, 3}; // N is constant expression return 0; }
这是可能的,因为
N
在声明时使用常量来保持常量和初始化,即使没有声明,它也满足常量表达式的条件constexpr
。 - 声明一些东西
那么我什么时候需要使用constexpr
?
- 像上面这样的对象
N
可以作为常量表达式使用而不需要声明constexpr
。所有对象都是如此:const
- 积分或枚举类型和
- 在声明时用一个本身就是常量表达式的表达式进行初始化
[这是由于§5.19/ 2:一个常量表达式不能包括一个子表达式,涉及“左值,右值修改,除非[...]整数或枚举类型的glvalue”感谢理查史密斯纠正我早些时候声称这对所有字面类型都是正确的。]
- 要使函数适合在常量表达式中使用,必须明确声明
constexpr
; 仅仅满足常量表达函数的标准是不够的。例:template<int N> class list { };
constexpr int sqr1(int arg) { return arg * arg; }
int sqr2(int arg) { return arg * arg; }
int main() { const int X = 2; list<sqr1(X)> mylist1; // OK: sqr1 is constexpr list<sqr2(X)> mylist2; // wrong: sqr2 is not constexpr return 0; }
我什么时候可以同时使用const
和constexpr
一起使用?
A.在对象声明中。当两个关键字都指向同一个被声明的对象时,这是不必要的。constexpr
意味着const
。
constexpr const int N = 5;
是相同的
constexpr int N = 5;
但是,请注意,可能会出现以下情况:关键字分别指向声明的不同部分:
static constexpr int N = 3;int main(){ constexpr const int *NP = &N; return 0;}
在这里,NP
被声明为一个地址常量表达式,即一个本身就是一个常量表达式的指针。(当通过将地址运算符静态/全局常量表达式生成的地址。这是可能的。)在这里,无论是constexpr
和const
是必需的:constexpr
总是指表达被宣布(在这里NP
),而const
指的是int
(它声明了一个指针-给const)。删除const
会导致表达式不合法(因为(a)非const对象的指针不能是常量表达式,(b)&N
实际上是指向常量的指针)。
B.在成员函数声明中。在C ++ 11中,也constexpr
暗示const
了成员函数。但是,这在C ++ 14中可能会改变。根据目前的草案,由于建议修改§7.1.5/ 8 ,constexpr
将const
仅针对对象,而不针对成员职能。因此,在C ++ 11下声明一个成员函数为
constexpr void f();
将不得不被宣布为
constexpr void f() const;
在C ++ 14下仍然可以用作const
函数。最好将你的constexpr
成员函数标记为const
现在,以免稍后改变很多代码。
发表评论
最新留言
关于作者
