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

标签 c++ static-methods static-members

我有一个宏,用于将键、值添加到注册表映射。 (假设 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 或其他任何被调用之前被调用。这是静态变量的预期。

但是,如果我从类更改为函数,那么代码似乎不再有效并提示“ key 已添加”

#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() 的相同原因。但是,为什么静态变量虚拟对象在静态函数中和在类的静态成员中的行为不同?

最佳答案

在一个类中,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();\
}

关于c++ - 类 C++ 初始化顺序的静态函数成员中的静态数据成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34206978/

相关文章:

c# - 实例方法是否不在c#中创建对象引用

java - 有效java中的静态工厂方法

c++ - 我可以用静态的、constexpr、类内初始化的数据成员做什么?

C# 静态类成员和 System.Windows.Controls.Image 性能问题

java - 静态字段是否为垃圾收集打开?

c++ - 将 int 添加到 vector 中

C++ 重载运算符 << 让我做噩梦

c++ - 向后可变参数模板

c++ - 从 OSx 上的自定义 url 打开 carbon c++ 程序

java - 是否可以从静态方法中获取类名?