Lot*_*ney 5 c++ initialization global-variables constexpr
如果我初始化constexpr变量foo在一个翻译单元,其具有非缺省值,然后一个初始化另一个constexpr变量bar与foo在另一翻译单元有可能是bar之前被初始化foo导致bar,是由初始化为零或缺省初始化foo。即与在非constexpr情况下(静态初始化顺序彻底失败有效)不同,编译器和链接器是否将分析依赖性顺序以确保正确的结果?
另外,constexpr变量模板如何受到影响?在单个翻译单元中,它们的初始化顺序是不确定的。
首选C ++ 17标准答案。
更新:这是一个最小的示例。有用; 那就是问题所在。至此,我99%确信这可以通过静态初始化命令惨败(TSIOF)来解决。但是,由于该问题的极端,阴险性质,我需要确认这是可以的。我相信该代码不会受到TSIOF的困扰,因为在xh命令a和bx.cc转换单元中包含了yh 。但是,AFAIU有2个翻译单元:一个包含a,另一个包含b。此外,AFAI-sort-of-U对a错误的多重定义不会出现,因为static关键字具有内部链接,但a仍然具有全局范围。
编译为:
clang++ -std=c++17 x.cc y.cc #or g++
Run Code Online (Sandbox Code Playgroud)
可能的输出:
in foo
Run Code Online (Sandbox Code Playgroud)
可能的输出:
assertion failed (core dumped)
Run Code Online (Sandbox Code Playgroud)
文件x.cc:
#include "x.h"
int main(){ assert(b == 42); foo(); }
Run Code Online (Sandbox Code Playgroud)
文件xh:
#pragma once
#include "y.h"
static constexpr int b = a+1;
Run Code Online (Sandbox Code Playgroud)
文件y.cc:
#include "y.h"
#include <iostream>
void foo(){
std::cout << " in foo \n";
}
Run Code Online (Sandbox Code Playgroud)
档案yh:
#pragma once
static constexpr int a=41;
void foo();
Run Code Online (Sandbox Code Playgroud)
这个程序可以保证输出in foo吗?
由于无法通过示例回答此问题,因此确实需要语言律师来提供相关的标准报价
这个问题是关于跨翻译单位的STIOF。有关模板变量的翻译单元内的STIOF的一个相关的,未回答的问题在这里
小智 5
在您的示例中,不存在可能的问题,因为y.cc 中的变量与x.cc 中的a变量不同。a所以没有发生跨翻译单元链接。
事实上, constexpr 变量之间不能存在交叉翻译单元链接。要点在于constexpr该值是在编译时计算的。
换句话说,当我们仍在单独编译翻译单元时,constexpr 必须解析为一个值。
\n\n因此,静态初始化顺序失败隐式不适用于constexpr变量,并且标准不需要提及在这种情况下要做什么。
编辑:根据要求,标准的相关部分是 10.1.5 (9)[dcl.constexpr]
\n\n\n\n\n在任何 constexpr 变量声明中,初始化的完整表达式应为常量表达式 (8.20)。
\n
这导致 8.20 (1) [expr.const] 具有以下注释:
\n\n\n\n\n[ 注意:常量表达式可以在翻译过程中求值。\xe2\x80\x94 尾注]
\n
这是下一页半条款背后的基本原理,但其本身足以排除交叉翻译单元引用。
\n