[英]Confusion about constant initialization
In cppref it gives the syntax of constant initialization : 在cppref中,它给出了常量初始化的语法:
static T & ref = constexpr;
static T object = constexpr;
Here's my two questions: 这是我的两个问题:
How could a lvalue reference T &
without const
be bound to a constexptr
,which is constant and unmodifiable ? 如何将左值引用T &
没有const
绑定到constexptr
,这是恒定且不可修改的?
I try to provide some example but failed: 我试着提供一些例子,但失败了:
static int& ref = 6; //error, need a `const`
constexpr int a = 6; static int& ref = a; //error, need a `const`
Is it a necessity for the object of constant initialization to be const
/ static
?In the standard it says: 常量初始化的对象是const
/ static
是必要的吗?在标准中它说:
Constant initialization is performed if a variable or temporary object with static or thread storage duration is initialized by a constant initializer for the entity. 如果具有静态或线程存储持续时间的变量或临时对象由实体的常量初始化程序初始化,则执行常量初始化。
Here the standard does not specify the obj to be const-qualified
/ static-qualified
. 这里标准没有将obj指定为const-qualified
/ static-qualified
。
What that is trying to say is that 试图说的是
static int a;
static int & ref = a;
static_assert(&a == &ref, "");
is okay. 没关系。 The initialisation is a form of constant initialisation because a
is a constant expression when evaluated as an lvalue (but only as an lvalue!), and as a result of that, &a == &ref
is a constant expression which evaluates to true
. 初始化是一种常量初始化的形式,因为当作为左值(但仅作为左值!)进行求值时, a
是一个常量表达式,因此, &a == &ref
是一个求值为true
的常量表达式。
Compare this to 比较这个
void f() {
int a;
static int & ref = a;
static_assert(&a == &ref, "");
}
This is invalid. 这是无效的。 Although the initialisation of ref
is technically valid, it becomes a dangling reference as soon as the function returns. 虽然ref
的初始化在技术上是有效的,但是一旦函数返回它就会成为悬空引用。 The next time the function is entered, a new int a
object is created. 下次输入该函数时,将创建一个新的int a
对象。 Because of that, &a == &ref
is not guaranteed to evaluate to true
. 因此, &a == &ref
不能保证评估为true
。 It is not a constant expression, and would have undefined behaviour if evaluated. 它不是一个常量表达式,如果进行求值,它将具有未定义的行为。
The confusion is due to the naming: the term constant in constant initialization [basic.start.static]/2 and constant expression [expr.const] means evaluable at compile time without heroic efforts(1) of the compiler . 混淆是由于命名: 常量初始化中的术语常量 [basic.start.static] / 2和常量表达式 [expr.const]意味着在编译时可以在没有编译器的英雄努力(1)的情况下进行评估 。 This differs from the concept of a constant object which means that the value of the object will not changed once defined. 这与常量对象的概念不同,这意味着一旦定义,对象的值就不会改变。
To illustrate the limit of evaluation at compile time let's look at the assembly of this code: 为了说明编译时的评估限制,让我们看一下这段代码的程序集:
//case 0
int i0 = 5;
int j0 = i0;//no compil-time initialized
//case 1
const int i1=5;
int j1=i1; //compil-time initialized
//case 2
extern const int i2=5;
int j2=i2; //compile-time initialized
//case 3
extern const int i3;
int j3=i3; //no compil-time initialization
//case 4
extern const int i4;
int j4=i4; //no compil-time initialization
const int i4=5;
Generated assembly by gcc 7.3: 由gcc 7.3生成的程序集:
_GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp
mov eax, dword ptr [rip + i0]
mov dword ptr [rip + j0], eax
mov eax, dword ptr [rip + i3]
mov dword ptr [rip + j3], eax
mov dword ptr [rip + j4], 5
ret
What is happening for: 发生了什么:
(1) the principle is that the language shall not be too complex to compile. (1)原则是语言不应太复杂,无法编译。 I just recycled the wording of the standard for template argument deduction where the term heroic effort appears litteraly. 我只是回收了模板论证演绎标准的措辞,其中术语英雄的努力似乎很明显。 The same principle is applied to define what is a constant expression. 应用相同的原则来定义什么是常量表达式。
"constant initialization" means the initializer is a constant expression. “常量初始化”意味着初始化器是一个常量表达式。 Neither the expression nor the variable need to be const-qualified. 表达式和变量都不需要是const限定的。
int x = 6;
at file scope is constant initialization. 在文件范围是常量初始化。
Reference: C++17 [basic.start.static]/2: 参考:C ++ 17 [basic.start.static] / 2:
Constant initialization is performed if a variable or temporary object with static or thread storage duration is initialized by a constant initializer for the entity. 如果与静态或线程存储持续时间的变量或临时对象由恒定初始化为实体初始化执行恒定的初始化 。
In the page you reference you can read 在您引用的页面中,您可以阅读
Sets the initial values of the static constants 设置静态常量的初始值
I point your attention over constants 我把注意力集中在常数上
So T
must be a constant type. 所以T
必须是一个常数类型。
So int const
is OK; 所以int const
就可以了; constexpr int
is OK because constexpr
imply const
; constexpr int
是可以的,因为constexpr
意味着const
; int
without const
(or without constexpr
that imply const
) is wrong. int
没有const
(或没有constexpr
暗示const
)是错误的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.