我有一个宏,我用它来添加键,值到注册表映射. (假设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()的原因相同.但是为什么静态变量虚拟的行为在静态函数中与在类的静态成员中时不同?
最佳答案 在类中,static关键字不会影响链接,但意味着它独立于类对象.无论你有多少次AddKey(MyClass,hello),只有一个函数NSP_MyClass :: A :: foo(),它只调用一次AddToMap.
在类或函数之外,static关键字给出了一个名称内部链接,这意味着包含它的每个编译单元都有自己的该名称版本.所以在你的第二个例子中,每个* .cc文件都有一个名为NS_MyClass :: A_foo()的不同函数,包括AddKey(MyClass,hello).这些函数中的每一个都会尝试调用AddToMap一次,从而为您提供碰撞问题.
使用内联而不是静态在头文件中有一个函数定义,但每次都有相同的函数:
#define AddKey(key, val)\
namespace NS_##key {\
inline bool A_foo() {\
static bool dummy = AddToMap(#key, #val);\
}\
static bool dummy_A = A_foo();\
}