在
cppref中,它给出了常量初始化的语法:
static T & ref = constexpr; static T object = constexpr;
这是我的两个问题:
Q1
低价参考T&没有const绑定到constexptr,它是常量且不可修改的?
我试着提供一些例子,但失败了:
static int& ref = 6; //error,need a `const` constexpr int a = 6; static int& ref = a; //error,need a `const`
Q2
常量初始化的对象是const / static是必要的吗?在the standard它说:
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.
这里标准没有将obj指定为const-qualified / static-qualified.
解决方法
混淆是由于命名:常量初始化
[basic.start.static]/2中的术语常量和常量表达式
[expr.const]意味着在编译时可以在没有编译器的英雄努力(1)的情况下进行评估.这与常量对象的概念不同,这意味着一旦定义,对象的值就不会改变.
为了说明编译时评估的限制,让我们看看这段代码的汇编:
//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;
由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
发生了什么:
> case 0,j0未在compil-time初始化,因为i0不是constant.[expr.constant]/2.7
>情况1和2,是编译时初始化的,因为它们适合于先前规则[expr.constant]/2.7.3的例外.
> case 3和case4,j3和j4在compil-time时没有初始化,因为它们不适合这个最后的规则异常,因为它们没有先前的初始化,(至少它可以在链接时解决,但这将是一个英雄的努力或依赖于实施质量)
(1)原则是语言不能太复杂,无法编译.我只是回收了模板论证演绎标准的措辞,其中术语英雄的努力似乎很明显.应用相同的原则来定义什么是常量表达式.