首要问题是:程序员如何确保通过静态初始化而不是通过动态初始化来初始化他的非本地静态变量?
由于始终进行零初始化,因此应该查看常量初始化。
3.6.2.2对象o的常量初始值设定项是一个表达式,它是一个常量表达式,除了它还可以调用constexpr o及其子对象的构造函数,即使这些对象是 非文字类类型[注意:这样的类可能有一个非平凡的类 析构函数 - 结束注意事项]。执行常量初始化:
- 如果每个完整表达式(包括隐式转换)那个 出现在带有静态或线程的引用的初始值设定项中 存储持续时间是一个常量表达式(5.19),参考是 绑定到左值,指定具有静态存储持续时间的对象 或临时(见12.2);
- 如果具有静态或线程存储持续时间的对象已初始化 通过构造函数调用,如果初始化full-expression是a 对象的常量初始值设定项;
- 如果具有静态或线程存储持续时间的对象不是 由构造函数调用初始化,如果对象是 值初始化或出现在其中的每个完整表达式 初始化程序是一个常量表达式。
我省略了引用,因为它在我的情况下并不重要。 I 如何理解标准是有3种情况:
假设我有以下课程:
struct X {
bool flag = false;
// = {} will break VS2013 CTP so in that case use the
// regular ctor, which sadly still can't be declared constexpr
std::aligned_storage<sizeof(int), alignof(int)>::type storage = {};
};
据我所知,这个类对于常量初始化是完全有效的(每个元素都可以不断初始化)。这是真的吗?
此类是否需要constexpr
构造函数?
C ++ 11以及C ++ 98是否保证了常量初始化?
附带问题:如果是/ dll,静态初始化什么时候完成?在加载时间内,还是可能会进一步延迟?
答案 0 :(得分:1)
了解这个问题背后的目的会很好。而且你的担忧是分配还是专门初始化。
但是,初始化的类型无关紧要,因为在编译时分配了所需的空间。根据您定义变量的方式,它将以.bss或.data部分结束。
如您所知,初始化仅用于在首次使用之前确保内存中的特定内容。如果你没有定义一个分配动态内存的构造函数,那么就不会有任何动态分配(如果你担心的话)。
对于简单的构造函数,我相信编译器将生成内联代码并使用相同的方法在编译时初始化对象(我不确定标准是什么谈论相同但是它可能是依赖于工具链的。)对于复杂的构造函数,当将图像加载到内存中时,将初始化非本地静态对象,并在加载堆栈帧时初始化本地静态对象。在任何情况下,您都应该在首次使用之前找到处于已知状态的对象。
答案 1 :(得分:1)
问题:在什么时候静态初始化完成 所以/ DLL?在加载时间内,还是可能会进一步延迟?
在Windows上,静态初始化发生在DllMain()调用之前获取DLL加载程序锁定之前。这严重限制了您在静态对象的构造函数中可以执行的操作。你不能加载任何其他DLL(LoadLibrary)或调用MIGHT导致加载DLL的任何其他函数,除了简单的初始化和Kernel32导出的函数之外,它几乎排除了任何东西。
有关详细信息,请参阅DllMain (MSDN)文档的最后几段。