constexpr
有什么区别和 const
?
最佳答案
基本含义和语法
这两个关键字都可以在对象和函数的声明中使用。应用于对象时的基本区别是:
const
将对象声明为常量。这意味着保证一旦初始化,该对象的值就不会改变,并且编译器可以利用这一事实进行优化。它还有助于防止程序员编写修改初始化后不打算修改的对象的代码。constexpr
声明一个对象适用于标准所谓的常量表达式。但请注意 constexpr
不是唯一的方法来做到这一点。当应用于函数时,基本的区别是:
const
只能用于非静态成员函数,不能用于一般函数。它保证成员函数不会修改任何非静态数据成员(可变数据成员除外,无论如何都可以修改)。constexpr
可以与成员和非成员函数以及构造函数一起使用。它声明了适合在常量表达式中使用的函数。编译器只会在函数满足特定条件 (7.1.5/3,4) 时才会接受它,最重要的是 (†):return
声明是允许的。对于构造函数,只允许使用初始化列表、typedef 和静态断言。 (不过,= default
和 = delete
也是允许的。)asm
声明,goto
声明,带有除 case
之外的标签的声明和 default
,try-block,非文字类型变量的定义,静态或线程存储期的变量的定义,不执行初始化的变量的定义。 常量表达式
如上所述,
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
}
这是可能的,因为 N
, 是常量并在声明时用文字初始化,满足常量表达式的标准,即使它没有声明 constexpr
.那么我实际上什么时候必须使用
constexpr
? N
以上可以用作常量表达式而无需声明constexpr
.这适用于所有对象:const
[这是由于 §5.19/2:常量表达式不得包含涉及“左值到右值修改的子表达式,除非 [...] 整数或枚举类型的泛左值 [...]” 感谢 Richard Smith 更正我的早先声称这适用于所有文字类型。]
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
}
我什么时候可以/应该同时使用两者,
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;
}
在这里,NP
被声明为一个地址常量表达式,即一个本身就是一个常量表达式的指针。 (当通过将地址运算符应用于静态/全局常量表达式来生成地址时,这是可能的。)这里,constexpr
和 const
需要:constexpr
总是指被声明的表达式(这里是 NP
),而 const
指 int
(它声明了一个指向常量的指针)。删除 const
会使表达式非法(因为 (a) 指向非常量对象的指针不能是常量表达式,并且 (b) &N
实际上是指向常量的指针)。B. 在成员函数声明中。 在 C++11 中,
constexpr
暗示 const
,而在 C++14 和 C++17 中则不然。在 C++11 下声明为的成员函数constexpr void f();
需要声明为constexpr void f() const;
在 C++14 下,为了仍可用作 const
功能。
关于c++ - `constexpr` 和 `const` 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14116003/