什么时候静态C ++类成员初始化?
似乎没有简单的答案,但是有什么假设可以安全地做出什么时候可以访问静态类字段?
编辑:唯一安全的假设似乎是所有静态在程序开始前(调用main
)初始化。 所以,只要我不从其他静态初始化代码引用静态,我应该没有什么可担心的?
该标准保证了两件事 – 在相同的翻译单元中定义的对象(通常意味着.cpp文件)按其定义( 而不是声明 )的顺序进行初始化:
3.6.2
具有静态存储持续时间的对象(basic.stc.static)的存储在进行任何其他初始化之前应该被初始化(dcl.init)。 零初始化和一个常量expression式的初始化统称为静态初始化; 其他的初始化都是dynamic初始化。 在任何dynamic初始化发生之前,初始化具有用常量expression式(expr.const)初始化的具有静态存储持续时间的PODtypes(basic.types)的对象。 在命名空间范围内在同一个翻译单元中定义并dynamic初始化的具有静态存储持续时间的对象应按其定义出现在翻译单元中的顺序进行初始化。
另一个保证的事情是,在翻译单元使用任何对象或函数之前,先完成来自翻译单元的静态对象的初始化:
命名空间作用域的对象的dynamic初始化(dcl.init,class.static,class.ctor,class.expl.init)是否在main的第一个语句之前完成是实现定义的。 如果初始化被推迟到main的第一个语句之后的某个时间点,它应该在第一次使用在同一个翻译单元中定义的任何函数或对象之前出现,作为初始化的对象。
我没有保证(特别是在不同的翻译单元中定义的对象的初始化顺序是实现定义的)。
编辑正如Suma的评论指出的那样,它也保证它们在 main
input之前被初始化。
它们在程序启动之前(即在进入main
之前)被初始化。
当在单个CPP文件中有两个或两个以上的定义(静态数据)时,它们将按照在文件中定义的顺序进行初始化(在文件中定义的更早/更高的定义一个是)。
当在多个CPP文件中有两个或多个(静态数据的)定义时,处理CPP文件的顺序是未定义的/实现特定的。 如果全局variables(在程序启动之前调用)的构造函数引用在另一个CPP文件中定义的另一个全局variables(可能尚未构build),则会出现此问题。 然而,Meyers的Effective C ++ (题为“ 确保全局对象在被使用之前被初始化 ”)的第 47项描述了解决方法。
-
在一个头文件中定义一个静态variables(它是静态的,所以你可以有多个实例,而不需要连接器抱怨)
-
让该variables的构造函数调用所需的任何东西(特别是构造在头文件中声明的全局单例)
…它说的是一种技术,可以在一些系统头文件中使用,例如,以确保即使您的静态variables的构造函数使用它,之前初始化cin
全局variables。
您在编辑中的最终结论是正确的。 但问题是类本身是静态的。 说起来我的代码会有类静态成员,不会引用其他全局数据/类静态成员,但是一旦你走这条路,事情就会很快出错。 我发现在实践中没有类静态数据成员而是类静态包装方法的一种方法。 这些方法可以将静态对象保存在其自身内部。 例如
TypeX* Class2::getClass1Instance() { static TypeX obj1; return &obj1; }
注意:之前的答案是:
另一个保证的事情是,在翻译单元使用任何对象或函数之前,先完成来自翻译单元的静态对象的初始化
这不完全正确,标准在这里被错误地推断出来。 如果在inputmain之前调用翻译单元的function,则这可能不成立。
它们可以在实现文件(.c / cpp / cc)文件中初始化。 不要在.h中初始化它们,因为编译器会抱怨多个定义。
它们通常在main之前初始化,但是order是未知的,因此避免了依赖关系。 他们当然可以在成员函数内访问。 请记住,静态成员的初始化顺序是未知的。 我build议将一个静态成员封装到静态函数,将检查成员是否已被初始化。
我相信它可以在执行过程中随时访问。 未定义的是静态variables的初始化顺序。
这个问题并没有一个完全无效的答案,但基本上它们是在控制传递到程序的入口点(main)之前初始化的。 (就我所知),它们被初始化的顺序是未定义的,并且可能是编译器特定的。
编辑:澄清,你添加的假设是正确的。 只要你只是在主入口后访问它,你不必担心什么时候/如何初始化。 它将在那个时候初始化。
我认为一个进程的主线程将按顺序执行以下五个步骤
-
CRT库的初始化
-
静态初始化
-
main()函数的执行
-
静态单元化
-
CRT库的单元化
你想从其他静态初始化代码引用静态? 也许下面的代码工作:
class A; static auto_ptr<A> a(auto_ptr<A>(&GetStaticA())); A &GetStaticA(void) { static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones if (a == NULL) { a = new A(); return *a; } }