gpt4 book ai didi

c++ - 为什么模板类的内联静态变量未初始化?

转载 作者:行者123 更新时间:2023-12-01 14:05:25 31 4
gpt4 key购买 nike

最小的例子和问题

在这个例子中,一个内联静态成员变量 c2非模板类在类成员实例化时初始化,成员变量c1模板类不是。有什么不同?为什么是 c1除非我通过获取其地址来强制初始化,否则不会被初始化,并且 c2是无条件初始化?

struct C1 {                        
C1() { std::cerr << "C1()\n"; }
};


struct C2 {
C2() { std::cerr << "C2()\n"; }
};

template<typename T>
struct Template {
inline static C1 c1;
};

struct Nontemplate {
inline static C2 c2;
};

int main() {
Template<int> a;
Nontemplate b;
(void)a;
(void)b;
}
// Output:
C2()

上下文和推理

这是最小示例的一些上下文。我有 Nontemplate继承自 Template<something> 的类,以及 c2 的构造函数取决于 c1 .我期待 c1之前创建 c2 ;然而,情况并非如此。
template<typename T>                                                     
struct Template {
inline static C1 c1;
};

struct Nontemplate : public Template<int> {
struct C2 {
C2() {
std::cerr << "Do something with Nontemplate::C1\n";
std::cerr << "&Nontemplate::c1 = " << &Nontemplate::c1 << "\n";
}
};
inline static C2 c2;
};

int main() {
Nontemplate b;
(void)b;
}
// Output:
Do something with Nontemplate::C1
&Nontemplate::c1 = 0x600ea8
C1()

代码是用 g++ 7.2 编译的, -std=c++17标志。两者 -O0-O2给出相同的结果。

最佳答案

类模板的隐式实例化只会导致它包含的声明的实例化。定义通常仅在需要定义存在的上下文中使用时才被实例化。

所以只要你不使用Template<int>::c1以需要其定义存在的方式(即通过 odr 使用它),则它根本不会被定义。

正如您提到的,odr 使用变量的一种方法是获取其地址。

即使你强制实例化变量,也不能保证它什么时候被初始化。
C1的构造函数不是 constexpr等等 Nontemlate::c1 的初始化不能是常量表达式。这意味着您将获得 Template<int>::c1 的动态初始化。 .作为模板特化一部分的全局静态变量的动态初始化是无序的,这意味着无法保证它们相对于全局静态变量的任何其他动态初始化以什么顺序发生。

同样Nontemlate::c2不是由常量表达式初始化的,因此也是动态初始化的。虽然 Nontemlate::c2具有部分有序的动态初始化(作为 inline 变量不是模板特化的一部分),它相对于 Template<int>::c1 仍然是不确定的。如上所述。

也没有严格要求 Template<int>::c1Nontemlate::c2main 之前初始化被输入。初始化是否推迟到稍后,但在相应变量的第一次 odr 使用之前,由实现定义。不过,我认为这种延迟主要用于运行时动态库加载。

避免全局静态存储持续时间变量排序问题的常用方法是使用返回对局部静态变量的引用的函数,即:

template<typename T>               
struct Template {
static auto& c1() {
static C1 instance;
return instance;
}
};

虽然这在经常调用时可能会影响性能,因为每次都必须检查本地静态的构造。

或者,如果初始化器可以做成一个常量表达式,那么做成变量 constexpr应该保证持续初始化,这意味着根本不会发生动态初始化,也不会出现排序问题。

关于c++ - 为什么模板类的内联静态变量未初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60794102/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com