“静态初始化顺序惨败”是constexpr变量的一个问题吗?

时间:2018-05-16 23:21:02

标签: c++ initialization global-variables constexpr

如果我在一个翻译单元中使用非默认值初始化constexpr变量foo,然后使用constexpr初始化另一个bar变量foo在另一个翻译单元中,可以在bar之前初始化foo,从而导致bar由零或默认初始化foo初始化。即,与非constexpr情况(静态初始化顺序失效有效)的情况不同,编译器和链接器会分析依赖顺序以保证正确的结果吗?

此外,constexpr变量模板如何受到影响?它们的初始化顺序在单个翻译单元中未定义。

C ++ 17标准答案首选。

更新: 这是一个最小的例子。有用;那就是问题所在。在这一点上,我99%确定 The Static Initialization Order Fiasco (TSIOF) 是安全的。但是,由于这个问题的极端,阴险的性质,我需要确认这是可以的。我相信此代码不会受到TSIOF的影响,因为x.h中的y.h在x.cc转换单元中包含ab。但是,AFAIU有2个翻译单元:一个包含a,另一个包含b。此外,AFAI-sort-of-U不会出现a错误的多重定义,因为static关键字赋予内部链接,但a仍具有全局范围< / em>的。

编译:

clang++ -std=c++17 x.cc y.cc  #or g++

可能的输出:

in foo

可能的输出:

assertion failed (core dumped)

file x.cc:

#include "x.h"
int main(){ assert(b == 42); foo(); }

file x.h:

#pragma once
#include "y.h"
static constexpr int b = a+1;

档案y.cc:

#include "y.h"
#include <iostream>
void foo(){
    std::cout << " in foo \n";
}

文件y.h:

#pragma once
static constexpr int a=41;
void foo();

此计划是否保证输出in foo

由于此问题无法通过示例回答,因此确实需要语言律师提供相关的标准报价

这个问题是关于翻译单位的STIOF。关于模板变量的翻译单元中有关STIOF的相关未答复问题是here

1 个答案:

答案 0 :(得分:2)

在您的示例中,没有可能的问题,因为y.cc中的a是与x.cc中的a不同的变量。因此没有发生交叉翻译单位联系。

实际上,不能是constexpr变量之间的交叉翻译单元链接。 constexpr的重点是该值是在编译时计算的。

换句话说,当我们仍在单独编译翻译单元时,constexpr必须解析为一个值。

由于这个原因,静态初始化命令Fiasco隐含地不适用于constexpr变量,并且标准中没有必要提及在该场景中要做什么。

编辑:根据要求,标准的相关部分是10.1.5(9)[dcl.constexpr]

  

在任何constexpr变量声明中,完整表达式   初始化应该是一个常量表达式(8.20)。

这导致8.20(1)[expr.const]具有以下注释:

  

[注意:在翻译期间可以评估常量表达式。 - 结束说明]

下一页半条款背后的理由是什么,但本身就足以排除交叉翻译单位的引用。