是否在调用构造函数之前初始化了静态成员?

时间:2014-11-18 13:17:27

标签: c++ static initialization member

我有一个带有std :: map静态成员的类。我在构造函数体的实现之前在相同的转换单元(相同的cpp文件)中初始化它。我的程序失败没有输出。我发现了一个称为静态初始化命令惨败的问题,但我不认为这可能是这种情况。

class Test {
public:
    static std::map<std::string, Test*> a;
    Test(std::string ID) {
        /* in my complete code  (where constructor
         * implementation and map initialization
         * are in a separate Test.cpp file), this fails, maybe
         * because the map is not initialized at the time
         * the constructor is being called by a sub class of Test */
        a.insert({ID, this});
    }
};

当我对其他变量进行静态初始化时,构造函数由Subclass Test调用。 是否有任何情况在初始化地图之前调用Test的构造函数?

4 个答案:

答案 0 :(得分:3)

“是否存在以前调用Test的构造函数的情况 地图是初始化的吗?“当然。所需要的就是那里 是一个静态实例Test在其他一些翻译单元中 一个定义地图的地方。 (构造函数的代码 Test的定义是无关紧要的。重要的是静态 Test的实例已定义。)

还有其他可能的场景:一些构造函数 例如,其他静态对象使用Test的本地实例。

此问题的常见解决方案是使用工厂方法 图:

std::map<std::string, Test*>& Test::registry()
{
    static std::map<std::string, Test*> theOneAndOnly;
    return theOneAndOnly;
}

这将导致在第一次需要时构建地图。

您使用的是哪个编译器?您无法为其指定初始值设定项 除非成员是const和,否则类定义中的静态成员 有积分或枚举类型。

答案 1 :(得分:0)

这就是标准所说的: -

具有静态存储持续时间(basic.stc.static)的对象的存储应在任何其他初始化发生之前进行零初始化(dcl.init)。使用常量表达式进行零初始化和初始化统称为静态初始化;所有其他初始化是动态初始化。具有使用常量表达式(expr.const)初始化的静态存储持续时间的POD类型(basic.types)的对象应在任何动态初始化发生之前初始化。在同一翻译单元的命名空间范围内定义并动态初始化的静态存储持续时间的对象应按其定义在翻译单元中出现的顺序进行初始化。

答案 2 :(得分:0)

C ++类中的

static声明定义了一个“属于”类本身的对象,而不是从该类创建的对象。 这意味着应该在Cpp文件中声明任何static成员的初始化。

使用语法:

std::map<std::string, Test*> Test::a = {};

所以对你的问题,不,没有这样的场景。在调用任何类构造函数之前,始终会初始化所有static个成员。

答案 3 :(得分:0)

解决问题的简单方法是使地图成为某个函数的static本地函数,以返回对它的引用。此函数可以是翻译单元私有函数或static类方法。

通常,翻译unots之间static个全局变量之间的依赖关系是个坏主意,因为在所有情况下都没有完全定义初始化顺序。

标准下的static局部变量在使用一次之前初始化。请注意,旧版本的visual studio在多线程初始化时存在问题,但不是新版本。