如果我在一个翻译单元中使用非默认值初始化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转换单元中包含a
和b
。但是,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
答案 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]具有以下注释:
[注意:在翻译期间可以评估常量表达式。 - 结束说明]
下一页半条款背后的理由是什么,但本身就足以排除交叉翻译单位的引用。