对于静态成员初始化,我使用嵌套的帮助器结构,它适用于非模板类。但是,如果封闭类由模板参数化,则嵌套初始化类不会被实例化,如果辅助对象没有在主代码中访问。为了说明,一个简化的例子(在我的例子中,我需要初始化一个向量)。
#include <string>
#include <iostream>
struct A
{
struct InitHelper
{
InitHelper()
{
A::mA = "Hello, I'm A.";
}
};
static std::string mA;
static InitHelper mInit;
static const std::string& getA(){ return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;
template<class T>
struct B
{
struct InitHelper
{
InitHelper()
{
B<T>::mB = "Hello, I'm B."; // [3]
}
};
static std::string mB;
static InitHelper mInit;
static const std::string& getB() { return mB; }
static InitHelper& getHelper(){ return mInit; }
};
template<class T>
std::string B<T>::mB; //[4]
template<class T>
typename B<T>::InitHelper B<T>::mInit;
int main(int argc, char* argv[])
{
std::cout << "A = " << A::getA() << std::endl;
// std::cout << "B = " << B<int>::getB() << std::endl; // [1]
// B<int>::getHelper(); // [2]
}
使用 g++ 4.4.1:
[1] 和 [2] 评论说:
A = 你好,我是 A。
按预期工作
[1] 未注释:
A = 你好,我是 A。 乙 =
我希望 InitHelper 初始化 mB
- [1] 和 [2] 未注释:
A = 你好,我是 A。 B = 你好,我是 B。
按预期工作 - [1] 已评论,[2] 未评论:
[3] 的静态初始化阶段的 Segfault
因此我的问题是:这是一个编译器错误还是位于监视器和椅子之间的错误?如果是后者:是否有一个优雅的解决方案(即没有显式调用静态初始化方法)?
更新 I:
这似乎是一种期望的行为(如 ISO/IEC C++ 2003 标准 14.7.1 中所定义):
除非类模板或成员模板的成员已被显式实例化或显式特化,否则当在需要成员定义存在的上下文中引用特化时,成员的特化将被隐式实例化;特别是,静态数据成员的初始化(以及任何相关的副作用)不会发生,除非该静态数据成员本身的使用方式要求该静态数据成员的定义存在。