class C++ 初始化顺序的静态函数成员中的静态数据成员
Static data member in static function member of class C++ order of initialisation
我有一个宏,用于将键、值添加到注册表映射。 (假设 AddToMap 位于在其他地方定义的全局静态对象上。)
在定义了不同的 classes 之后,AddKey 宏在代码的不同位置被调用(classes 的某种注册表)。代码分成很多.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 或其他任何被调用之前被调用。这是静态变量的预期。
但是,如果我从 class 更改为正常运行,那么代码似乎不再有效并抱怨 "key has already been added"
#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() 的相同原因。但是,为什么在静态函数中与在 class 的静态成员中静态变量虚拟对象的行为不同?
在 class 中,static
关键字不影响链接,但意味着它独立于 class 对象。无论你有多少次 AddKey(MyClass, hello)
,只有一个函数 NSP_MyClass::A::foo()
,它只调用一次 AddToMap
。
在 class 或函数之外,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();\
}
我有一个宏,用于将键、值添加到注册表映射。 (假设 AddToMap 位于在其他地方定义的全局静态对象上。) 在定义了不同的 classes 之后,AddKey 宏在代码的不同位置被调用(classes 的某种注册表)。代码分成很多.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 或其他任何被调用之前被调用。这是静态变量的预期。
但是,如果我从 class 更改为正常运行,那么代码似乎不再有效并抱怨 "key has already been added"
#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() 的相同原因。但是,为什么在静态函数中与在 class 的静态成员中静态变量虚拟对象的行为不同?
在 class 中,static
关键字不影响链接,但意味着它独立于 class 对象。无论你有多少次 AddKey(MyClass, hello)
,只有一个函数 NSP_MyClass::A::foo()
,它只调用一次 AddToMap
。
在 class 或函数之外,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();\
}