类C++的静态函数成员中的静态数据成员初始化顺序

Static data member in static function member of class C++ order of initialisation

本文关键字:数据成员 初始化 静态 顺序 成员 C++ 静态函数      更新时间:2023-10-16

我有一个宏,用来向注册表映射添加键和值。(假设AddToMap位于全局静态对象上,该对象在其他位置定义。)在定义了不同的类(类的某种注册表)后,AddKey宏在代码中的不同位置被调用。代码被划分为许多具有复杂依赖性的.h和.cc文件。

我有以下一段代码可以工作:

#define AddKey(key, val)
namespace NSP_##key {
class A {
    public:
        static bool foo() {
        static bool dummy = AddToMap(#key, #val);
}
};
static bool dummy_A = A::foo();
}

`

我想知道静态变量dummy是如何创建和初始化的。当我使用GDB时,我看到这个A::add在main或其他任何东西被调用之前就被调用了。这是静态变量所期望的。

然而,如果我从类更改为函数,那么代码似乎不再工作,并抱怨"密钥已经添加"

#define AddKey(key, val)
namespace NS_##key {
    static bool A_foo() {
    static bool dummy = AddToMap(#key, #val);
}
static bool dummy_A = A_foo();
}

我理解dummy_A必须是静态的,因为C++中有一个定义规则,A_foo()也是如此。但是,为什么静态变量dummy在静态函数中的行为与在类的静态成员中的行为不同呢?

在类中,static关键字不影响链接,但意味着它独立于类对象。无论有多少次AddKey(MyClass, hello),都只有一个函数NSP_MyClass::A::foo(),它只调用AddToMap一次。

在类或函数之外,static关键字提供了一个名称内部链接,这意味着包含它的每个编译单元都有自己的名称版本。因此,在第二个示例中,对于包含AddKey(MyClass, hello)的每个*.cc文件,都有一个名为NS_MyClass::A_foo()的不同函数。这些函数中的每一个都将尝试调用AddToMap一次,从而产生冲突问题。

使用inline而不是static在头文件中有一个函数定义,但每次都是相同的函数:

#define AddKey(key, val)
namespace NS_##key {
    inline bool A_foo() {
        static bool dummy = AddToMap(#key, #val);
    }
    static bool dummy_A = A_foo();
}