C ++中的静态初始化

时间:2012-07-10 14:20:54

标签: c++ visual-c++ c++-cli

大家好!

我正在开发visual C ++(托管代码)上的winForm应用程序。 此应用程序链接本机静态库,其中包含带有静态变量初始化的代码块:

Cls.h

class Cls
{
public:
    static Cls* getInstance();

private:
    static Cls _instance;
protected:
    Cls(void);
};

Cls.cpp

#include "StdAfx.h"
#include "Cls.h"

Cls::Cls(void)
{
}

Cls Cls::_instance;

Cls* Cls::getInstance()
{
    return &_instance;
}

我可以成功链接这些库,但是当我尝试使用 getInstance()方法时,在调用我的应用程序的main函数之前会出现运行时错误。

这是第三方库,所以我无法重建它或以任何其他方式重新定义 Cls 类。

App项目使用 / clr ,入口点定义为 main

我厌倦了搜索解决方案。我发现我必须改变切入点,但我不知道什么值是正确的。

请帮忙!

1 个答案:

答案 0 :(得分:4)

你遇到了臭名昭着的“静态初始化命令惨败”。当静态对象在两个翻译单元中定义时,它是未指定的,首先被初始化;所以,如果一个的构造函数引用另一个,那么在初始化之前你最终可能会访问它。唯一的保证是它们将在main开始之前全部初始化。

最好的解决方案是避免使用静态对象。特别是,你正在使用的Singleton反模式在C ++中是相当棘手的,并且通常比它的价值更麻烦。

如果你真的想这样做,那么你可以通过在函数中定义静态对象来解决这个惨败:

Cls* Cls::getInstance()
{
    static Cls _instance;
    return &_instance;
}

这样做的缺点是它引入了“破坏命令惨败”(从另一个静态对象的析构函数访问可能不安全),并且它在某些编译器中可能不是线程安全的(尽管它应该是在任何声称符合C ++ 11的规定中)。如果构造是线程安全的,那么每次访问都会有(小)运行时成本,如果您遇到极端性能问题,这可能会成为一个问题。

更新:我刚刚注意到你说这个邪恶的阶级不在你的控制范围之内,无法改变。在这种情况下,您的选择是:

  • 摆脱这个库并使用不太疯狂的东西,或
  • main开始之前,请注意不要访问任何静态数据;特别是,请遵循我的建议,避免使用自己的静态物体。