tch*_*tow 9 c++ inline static-variables initialization-order inline-variable
我知道这个问题已经被问过很多次了,但这似乎是一个略有不同的变化,我无法弄清楚。
考虑以下代码:
#include <cstdio>
struct TestValue;
inline const TestValue* v_ptr = nullptr;
struct TestValue {
static const TestValue v1;
TestValue() {
v_ptr = this;
printf("TestValue Initialized at %p\n", this);
}
};
struct CallTest {
CallTest() {
printf("CallTest Initalized at %p\n", this);
printf("v_ptr = %p\n", v_ptr);
}
};
const inline TestValue TestValue::v1{};
const inline CallTest ct{};
int main() {}
Run Code Online (Sandbox Code Playgroud)
我使用的是 C++17 或更高版本,它增加了对外部静态初始化内联变量的支持。我试图理解使用内联说明符“out of line”时围绕初始化顺序的保证。请注意, v1被声明为 TestValue 的静态变量,然后稍后但在 之前内联定义ct。令人惊讶的是(至少对我来说),使用 Clang 14.0.3,程序打印:
CallTest Initalized at 0x404059
v_ptr = (nil)
TestValue Initialized at 0x404068
Run Code Online (Sandbox Code Playgroud)
如果我移出v1它在之前的同一行中TestValue声明和ct定义的位置,我会得到预期的输出:
TestValue Initialized at 0x404059
CallTest Initalized at 0x404068
v_ptr = 0x404059
Run Code Online (Sandbox Code Playgroud)
我对我对标准的理解充满信心,因为第二个示例保证首先打印 TestValue。但是第一个案例呢?
我不确定前向声明的合法性v1,然后稍后再内联定义它,但仅此一点似乎就可以了: https: //eel.is/c++draft/dcl.inline#note-2
至于顺序,我的理解是v1和ct应该是“部分排序”:因为它们是内联的https://eel.is/c++draft/basic.start.dynamic#1
然后,由于其中至少一个是部分有序的(另一个不是无序的),因此它们按照定义的顺序进行初始化:https://eel.is/c++draft/basic.start.dynamic#3.1
也许我误读了部分有序和无序的定义?不是v1部分排序的,因为内联说明符出现在定义的后面 - 即。排序仅适用于声明处的内联?在这种情况下,我仍然不明白它如何变得无序;另一种可能是有效的。还需要指定 inline 来修复 ODR 违规,因此它似乎正在做一些事情。(我从上述情况中发现了这个错误,但是其中TestValue和CallTest以及它们各自的定义被分割到多个标头中,CallTest标头包括TestValue)。
我还发现 GCC 尊重 和 的定义顺序,v1而ct如上所述,Clang 总是ct首先初始化。
编辑:Clang 中的另一个观察结果 - 如果我 makev1和ctconstexpr (从构造函数中删除副作用),则地址v1小于ct- 它们按预期顺序初始化。
我还在上面的示例中意识到const inline CallTest ct{}具有内部链接,而v1外部是静态成员。我修复了这个问题,但ct仍然首先“错误”初始化。不确定这是否会影响预期的初始化顺序。
我也进行了这个测试:
extern const TestValue v1;
const inline TestValue v1{};
extern const inline CallTest ct{};
Run Code Online (Sandbox Code Playgroud)
其中首先初始化v1。我不明白为什么,如果v1是静态类变量,它的初始化顺序与普通的外部变量不同。
看起来这应该在 Clang 16 中修复:https://github.com/llvm/llvm-project/commit/f9969a3d28e738e9427e371aac06d71269220123
演示: https: //clang.godbolt.org/z/vMrhTTW8v
| 归档时间: |
|
| 查看次数: |
420 次 |
| 最近记录: |