是“静态初始化命令惨败”吗?对constexpr变量的关注? [英] Is the "static initialization order fiasco" a concern for constexpr variables?

查看:98
本文介绍了是“静态初始化命令惨败”吗?对constexpr变量的关注?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



首选C ++ 17标准答案。



更新:
这是一个最小的示例。有用;那就是问题所在。目前,我有99%的把握从 静态初始化订单惨败(TSIOF) 。但是,由于该问题的极端,阴险性质,我需要确认这是可以的。我相信该代码不会受到TSIOF的影响,因为在xh订单 a b 在x.cc转换单元中。但是,AFAIU有2个翻译单元:一个包含a,另一个包含b。此外,AFAI-sort-of-U不会出现 a 错误的多重定义,因为static关键字赋予了内部 linkage a 仍然具有全局 scope



编译为:

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

可能的输出:

  in foo 

可能的输出:

 断言失败(核心转储)

文件x.cc:

  #include xh 
int main() {assert(b == 42); foo(); }

文件xh:

  #pragma一旦
#include yh
静态constexpr int b = a + 1;

文件y.cc:

  #include yh 
#include< iostream>
void foo(){
std :: cout<< 在富\n;
}

文件yh:

  #pragma一旦
静态constexpr int a = 41;
void foo();

此程序是否保证在foo中输出



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



这个问题与跨翻译单位的STIOF有关。有关模板变量的翻译单元内的STIOF的一个相关未解决的问题是此处

解决方案

在您的示例中,由于 a 与x.cc中的 a 是不同的变量。因此,没有发生跨翻译单元链接。



事实上,constexpr变量之间没有不能跨翻译单元链接。 constexpr 的要点是,该值是在编译时计算的。



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



因为这一点,静态初始化顺序Fiasco隐式不适用于 constexpr 变量,因此该标准无需提及在该情况下该怎么做。 / p>

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



< blockquote>

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


这引出8.20(1)[expr.const]并具有以下注释:


[注意:常量表达式可以在翻译过程中求值。 —尾注]


这是下一页和一半子句背后的原理,但其本身足以防止交叉翻译单位参考。


If I initialize a constexpr variable foo with a non-default value in one translation unit and then a initialize another constexpr variable bar with foo in another translation unit is it possible for bar to be initialized before foo resulting in a bar that was initialized by a zero-or-default-initialized foo. i.e. Unlike in the non-constexpr case (where the static initialization order fiasco is in effect) will the compiler and linker analyze dependency ordering to guarantee the correct result?

Additionally, how are constexpr variable templates affected? Their initialization ordering is undefined WITHIN single translation units.

C++17 standard answers preferred.

UPDATE: Here is a minimal example. It works; that's the problem. At this point I'm 99% sure that this is safe from The Static Initialization Order Fiasco (TSIOF). However, due to the extreme, insidious nature of that problem I need to get confirmation that this is ok. I believe this code does not suffer from TSIOF since the inclusion of y.h in x.h orders a and b within the x.cc translation unit. However, AFAIU there are 2 translation units: one containing a, the other containing b. Furthermore, AFAI-sort-of-U a multiple definition of a error does not arise because the static keyword imparts internal linkage but a still has global scope.

compiled with:

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

possible output:

in foo

possible output:

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;

file y.cc:

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

file y.h:

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

Is this program guaranteed to output in foo?

Since this question can't be answered via example it really needs a language lawyer to provide relevant standard quotes

This question is about STIOF across translation units. A related, unanswered question about STIOF within translation units for template variables is here

解决方案

In your example, there is no possible issue because the a in y.cc is a different variable from a in x.cc. So there is no cross-translation unit linkage happening.

In fact, there cannot be cross-translation unit linkage between constexpr variables. The whole point of constexpr is that the value is calculated at compilation time.

In other words, the constexpr must resolve to a value while we are still compiling the translation unit in isolation.

Because of the this the Static Initialization Order Fiasco implicitly does not apply to constexpr variables, and there is no need for the standard to mention what to do in that scenario.

Edit: as requested, the relevant part of the standard is 10.1.5 (9)[dcl.constexpr]

In any constexpr variable declaration, the full-expression of the initialization shall be a constant expression (8.20).

Which leads to 8.20 (1) [expr.const] that has the following note:

[ Note: Constant expressions can be evaluated during translation. — end note ]

Which is the rationale behind the next page and a half of clauses, but is enough by itself to preclude cross-translation unit references.

这篇关于是“静态初始化命令惨败”吗?对constexpr变量的关注?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆