C++ 变量上的 const 与 constexpr

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13346879/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:13:03  来源:igfitidea点击:

const vs constexpr on variables

c++variablesc++11constconstexpr

提问by fredoverflow

Is there a difference between the following definitions?

以下定义之间有区别吗?

const     double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;

If not, which style is preferred in C++11?

如果不是,那么在 C++11 中更喜欢哪种风格?

回答by Howard Hinnant

I believe there is a difference. Let's rename them so that we can talk about them more easily:

我相信是有区别的。让我们重命名它们,以便我们可以更轻松地讨论它们:

const     double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;

Both PI1and PI2are constant, meaning you can not modify them. However onlyPI2is a compile-time constant. It shallbe initialized at compile time. PI1may be initialized at compile time or run time. Furthermore, onlyPI2can be used in a context that requires a compile-time constant. For example:

这两个PI1PI2是不变的,这意味着你不能修改它们。然而,它只是PI2一个编译时常量。它在编译时初始化。 PI1可以在编译时或运行时初始化。此外,只能PI2在需要编译时常量的上下文中使用。例如:

constexpr double PI3 = PI1;  // error

but:

但:

constexpr double PI3 = PI2;  // ok

and:

和:

static_assert(PI1 == 3.141592653589793, "");  // error

but:

但:

static_assert(PI2 == 3.141592653589793, "");  // ok

As to which you should use? Use whichever meets your needs. Do you want to ensure that you have a compile time constant that can be used in contexts where a compile-time constant is required? Do you want to be able to initialize it with a computation done at run time? Etc.

至于你应该使用哪个?使用满足您需求的任何一种。你想确保你有一个编译时常量可以在需要编译时常量的上下文中使用吗?您是否希望能够使用在运行时完成的计算来初始化它?等等。

回答by Pete Becker

No difference here, but it matters when you have a type that has a constructor.

这里没有区别,但是当您的类型具有构造函数时这很重要。

struct S {
    constexpr S(int);
};

const S s0(0);
constexpr S s1(1);

s0is a constant, but it does not promise to be initialized at compile-time. s1is marked constexpr, so it is a constant and, because S's constructor is also marked constexpr, it will be initialized at compile-time.

s0是一个常量,但它不承诺在编译时初始化。s1被标记constexpr,所以它是一个常量,并且因为S的构造函数也被标记constexpr,它将在编译时初始化。

Mostly this matters when initialization at runtime would be time-consuming and you want to push that work off onto the compiler, where it's also time-consuming, but doesn't slow down execution time of the compiled program

大多数情况下,这很重要,因为运行时初始化会很耗时,并且您想将这项工作推到编译器上,这也很耗时,但不会减慢已编译程序的执行时间

回答by Ajay yadav

constexprindicates a value that's constant and known during compilation.
constindicates a value that's only constant; it's not compulsory to know during compilation.

constexpr表示一个在编译过程中恒定且已知的值。
const表示一个只有常量的值;在编译期间不必知道。

int sz;
constexpr auto arraySize1 = sz;    // error! sz's value unknown at compilation
std::array<int, sz> data1;         // error! same problem

constexpr auto arraySize2 = 10;    // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr

Note that const doesn't offer the same guarantee as constexpr, because const objects need not be initialized with values known during compilation.

请注意,const 不提供与 constexpr 相同的保证,因为不需要使用编译期间已知的值初始化 const 对象。

int sz;
const auto arraySize = sz;       // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation

All constexpr objects are const, but not all const objects are constexpr.

所有 constexpr 对象都是 const,但并非所有 const 对象都是 constexpr。

If you want compilers to guarantee that a variable has a value that can be used in contexts requiring compile-time constants, the tool to reach for is constexpr, not const.

如果您希望编译器保证变量具有可在需要编译时常量的上下文中使用的值,则需要使用的工具是 constexpr,而不是 const。

回答by Jnana

A constexprsymbolic constant must be given a value that is known at compile time. For example:

constexpr符号常数,所以必须考虑到在编译时已知的值。例如:

?constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    constexpr int c2 = n+7;   // Error: we don't know the value of c2
    // ...
}

To handle cases where the value of a “variable” that is initialized with a value that is not known at compile time but never changes after initialization, C++ offers a second form of constant (a const). For Example:

为了处理使用编译时未知但在初始化后永远不会更改的值初始化的“变量”值的情况,C++ 提供了第二种形式的常量(const)。例如:

?constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    const int c2 = n+7; // OK, but don't try to change the value of c2
    // ...
    c2 = 7; // error: c2 is a const
}

Such “constvariables” are very common for two reasons:

这种“常量变量”很常见,原因有两个:

  1. C++98 did not have constexpr, so people used const.
  2. List item “Variables” that are not constant expressions (their value is not known at compile time) but do not change values after initialization are in themselves widely useful.
  1. C++98 没有 constexpr,所以人们使用const
  2. 不是常量表达式(它们的值在编译时未知)但在初始化后不更改值的列表项“变量”本身就非常有用。

Reference : "Programming: Principles and Practice Using C++" by Stroustrup

参考:Stroustrup 的“编程:使用 C++ 的原则和实践”