c++ - 为什么模板的静态成员在稍后在同一翻译单元中定义的对象之后初始化?
问题描述
考虑以下(人工)示例:
#include <iostream>
int f() {
return 42;
}
template <typename T>
struct S {
static int I;
};
template <typename T>
int S<T>::I = f();
template <typename T>
int g() {
return S<T>::I;
}
int global = g<int>();
int main() {
std::cout << global << std::endl;
}
它在使用 gcc 4.8.4 编译并运行时打印 0:
$ g++ test.cc
$ ./a.out
0
这表明在初始化 forglobal
之前运行动态初始化 for S<T>::I>
。但是,根据this SO answer,
在同一个翻译单元中定义的对象(通常是 .cpp 文件)按照它们的定义顺序进行初始化
为什么动态初始化在 forglobal
之前运行S<T>::I>
而不是按照它们的定义顺序运行,是否可以在global
之后强制初始化?
解决方案
由于 的初始化S<T>::I
是无序的,因此 的值S<int>::I
可以是 0(如果在 之后初始化global
)或 42(如果在 之前初始化global
)。
虽然您不能强制编译器在I
之前进行初始化global
,但只要稍微更改您的代码,您就可以使用用于对不同翻译单元中定义的静态变量进行排序的相同方法。通过更改I
为将其值存储在内部静态变量中的函数,您可以确保它在global
.
template <typename T>
struct S {
static int I() {
static int i = f();
return i;
}
};
template <typename T>
int g() {
return S<T>::I();
}
推荐阅读
- android - 使用 ExoPlayer 处理耳机按钮点击
- sql - 将表中的每一行与其他每一行进行比较,一次且仅一次
- sql - 使用 postgresql 计算 datediff 并产生年数
- odoo - 如何在 Odoo 中定义自定义设置
- git - 如何解决致命:无法访问,CONNECT 后从代理收到 HTTP 代码 400
- mysql - 如何使用用户提交的变量进行查询并保存?
- ios - 从 UITabBarController 模态显示 ViewController 而不隐藏标签栏
- python - 如何使用 Python 从 shell 连接 MySQL 工作台?
- r - 如何创建对用户输入做出反应的反应数据框_
- java - 如何在 Java 中打开带有锚点的 URL?