我有一个奇怪的问题,
在A类中声明一个名称为B类的静态成员variables。 并在cpp文件中初始化。 但B类的构造函数从来没有被调用过。 我尝试使用一些小testing,testing构造函数可以正常调用。 所以我们的生产系统很奇怪
这样的代码,在hpp :
class Test { public: Test() { ofstream file("/tmp/wup.txt",ios::app); file << "wup in test" << endl; file.close(); } }; //## An extended personality class TsdNAExtPersonality : public TsdNAPersonality{ public: TsdNAExtPersonality( s_gg62_personRec * gg62Header, TsdNAFunctionType requiredFunctionType); private: static Test test; public: TsdNAExtPersonality( string * personalityFile, TsdNAFunctionType requiredFunctionType); };
而在另一个cpp文件我初始化
Test TsdNAExtPersonality::test;
我尝试了几种方法,但是我发现所有的方法都是无用的。
环境是HP-UX,编译是aCC
所以我的问题是:
有没有编译选项会影响variables? 换句话说,所有的静态variables都不会被初始化。
从C ++的标准来看,它应该在库加载的时候被调用,对吧?
我用同样的方法把另一个静态的int值,它可以被初始化。 但是类构造函数不叫,很奇怪。
我的代码中有没有错误?
从C ++的标准来看,它应该在库加载的时候被调用,对吧?
不可以。静态存储持续时间的对象的动态初始化保证在执行在相同的翻译单元中定义的任何功能之前发生。 如果没有这样的功能,或者你的程序不会调用它们,那么不能保证它会被初始化。
我用同样的方法把另一个静态的int值,它可以被初始化。 但是类构造函数不叫,很奇怪。
一个int
变量在程序启动之前是静态初始化的,只要它的初始化是恒定的。
有没有编译选项会影响变量?
不是我所知道的,但我不熟悉你的平台。 您可以通过在一个函数中对其进行范围控制来更好地控制对象的创建:
static Test & test() { static Test test; return test; }
现在保证在函数第一次被调用时被初始化。 当然,你需要记得在某个时候调用它。
C ++程序的启动和关闭是灰色区域,因为不清楚你已经可以使用多少代码(因为它已经被初始化),还有多少还没有开始。 在关闭时,析构函数也会发生同样的情况……当你的静态实例被销毁时,有多少个子系统已经被关闭,这并不清楚。
而且,对于任何可能失败的东西,永远都不应该使用静态初始化,在开始之前或者在结束之后进行调试可能会非常困难。
还要注意,静态初始化的顺序没有被定义(除了相对于同一编译单元中的其他静态),它可以从一个编译改变到下一个。 这意味着你可能对一个工作程序感到满意,直到出于某种奇怪的原因,你得到一个不同的初始化顺序,并且在没有任何相关的代码改变的情况下停止工作。
对于非常简单的东西,使用静态初始化是可以的,对于其他任何东西都不是,你应该做适当的控制初始化。
我认为你的编译器有一个bug。
在linux / g ++上运行这个简单的代码给出了预期的结果:
#include <iostream> using namespace std; class A { public: A() { cout << "Hallo" << endl; } }; class B { public: static A a; }; AB::a; // < here the constructor must be called! int main() { cout << "Main runs" << endl; return 0; }
结果是:
Hallo Main runs
当构造静态数据成员时,必须调用构造函数(上面的注释行)。
C ++中的静态初始化是:
因此,你最好的选择是在第一个函数调用时进行初始化
int fn() { static int result = 42; return result; }
编辑 :
如果你想在main之前初始化:
struct Initialize { Initialize() { fn(); } } Initialize initialize;