我有一个宏,用于将键、值添加到注册表映射。 (假设 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/