是否保证初始化顺序
Is initialization order guaranteed
我正在使用类似以下代码部分的东西来进行一些初始化。我知道p<T>::i_
的初始化是无序的。我相信h
是有序的,所以我应该能够推断它的初始化顺序。假设p
的标头包含在h
的定义之前,有什么保证p<T>::i_
会在h
之前初始化吗?
struct helper
{
template <typename T>
helper(const T&, int i)
{
p<T>::i_::push_back(i);
}
};
static helper h;
类p的定义如下。
template <typename T>
struct p
{
static std::vector<int> i_;
};
template <typename T>
std::vector<int> p<T>::i_;
具有静态存储持续时间的对象的初始化顺序在转换单元之间是未定义的,并且在每个转换单元内是顺序的。
在您的特定情况下,情况会更加复杂,因为具有静态存储的对象之一是模板类的静态成员。实际上,这意味着访问成员p<T>::i_
的每个翻译单元都将创建符号,并添加适当的初始化代码。稍后,链接器将选择其中一个实例并保留它。即使看起来p<T>::i_
是在您的翻译单元中的h
之前定义的,您也不知道链接器将保留p<T>::i_
的哪个实例,并且该实例可能位于不同的翻译单元,因此顺序无法保证。
一般来说,拥有全局对象是个坏主意,我建议你尝试在没有这些全局的情况下重新设计你的程序。
全局或命名空间范围内的对象是在一个转换单元内自上而下构建的。不同翻译单元之间的全局或命名空间级别的构造顺序没有定义。在转换单元之间安排初始化的最合理方法是将对象包装在合适的访问器函数中,例如:
template <typename T>
something<T>& get() {
static something<T> values;
return value;
}
然而,请注意,这在C++03中不是线程安全的(因为C++03无论如何都没有线程的概念)。它在C++11中是线程安全的。
不,不能保证。
然而,你能做的是:
template<typename T>
std::vector<int>& registry() {
static std::vector<int> reg;
return reg;
}
...
registry<T>().push_back(i);
...
更好的做法是在创业期间避免做一些过于聪明的事情。
main
开始前或结束后的调试是一场真正的噩梦(IMO甚至没有在标准中涵盖100%)。简单的注册是可以的,但永远不要做任何可能失败的事情。
多年来,我从这种方法转向了显式初始化/关闭,并且从未回头。
相关文章:
- lambda 作为接受其他参数的参数的初始化顺序
- 大括号或等于初始值设定项初始化顺序
- 类内初始化与构造函数初始化列表的顺序
- C++ 模板中的静态常量初始化顺序
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- 视觉C++:在 DLL 加载期间,全局变量初始化顺序是否具有确定性?
- 构造函数中没有参数的对象类成员按什么顺序初始化?
- 销毁 pthread 互斥体和 C++ 中的取消初始化顺序
- 线程局部变量的初始化顺序
- 初始化值是否保证通过其自己的地址反映,而不考虑内存顺序
- 类静态变量初始化顺序
- 具有静态存储持续时间的常量初始化变量的初始化顺序
- 解析 CRTP 初始化顺序
- 初始化相等C++的顺序
- 内联初始化的静态 const 类成员的初始化顺序保证
- 使用constexpr的全局初始化顺序
- 初始化与类类型相同的静态成员(静态初始化顺序问题)
- 结构化绑定的标识符是否按顺序初始化?
- c++中的求值顺序初始化数组
- c++标准和C语言在哪里说的是一样的:编译单元(.cpp文件)中的变量是按照声明的顺序初始化的