我有一个宏,我用它来为注册表地图添加键值。 (假设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()的原因相同。但是为什么静态变量虚拟的行为在静态函数中与在类的静态成员中时不同?
答案 0 :(得分:1)
在一个类中,static
关键字不会影响链接,但意味着它独立于类对象。无论您有多少次AddKey(MyClass, hello)
,只有一个函数NSP_MyClass::A::foo()
,只需调用AddToMap
一次。
在类或函数之外,static
关键字给出了名称内部链接,这意味着包含它的每个编译单元都有自己的该名称版本。因此,在第二个示例中,每个* .cc文件都有一个名为NS_MyClass::A_foo()
的不同函数,其中包含AddKey(MyClass, hello)
。这些函数中的每一个都会尝试调用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();\
}