如果未使用静态 menber,则静态成员变量是否在模板类中初始化

Is static member variable initialized in a template class if the static menber is not used?

本文关键字:初始化 是否 变量 静态 未使用 menber 静态成员 如果      更新时间:2023-10-16

如果不使用静态成员,静态成员变量是否在模板类中初始化?我用它来注册类型。

template<class T>
class A
{
    static bool d;
};
template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();
int main()
{
   A<int> a;
   return 0;
}

我找到了测试它的方法。它打印 1 个而不是 2。regist(( 不称为 abd,静态成员未初始化。我的测试是在 VC110 编译器上进行的。我也在网上测试它

#include <iostream>
using namespace std;
int i = 1;
template<class T>
void regist()
{
    ++i;
}
template<class T>
class A
{
    static bool d;
};
template<class T> bool A<T>::d = [](){regist<A<T>>(); return true;}();
int main()
{
    A<int> a;
    cout << i << endl;
    return 0;
}

C++草案标准的相关部分属于14模板,该模板14.7.1 隐式实例化2 段说(强调我的(:

除非类模板或成员模板的成员已显式实例化或显式专用化,否则当在需要成员定义的上下文中引用专用化时,将

隐式实例化成员的专用化;特别是,除非静态数据成员本身的使用方式需要定义静态数据成员,否则不会发生静态数据成员的初始化(以及任何关联的副作用(要存在的数据成员。

我们还可以看到第8段,其中说:

模板的隐式实例化不会导致该类的任何静态数据成员被隐式实例化。

但是,如果您按如下方式向第二种情况添加显式实例化,您将看到2结果:

template<> bool A<int>::d = [](){regist<A<int>>(); return true;}();

是的,它已初始化运行此示例程序,但只是因为它被强制存在。

template <class T>                                                                 
struct A                                                                           
{                                                                                  
    static int b;                                                                  
};                                                                                 
template <class T> int A<T>::b = 10;                                               
#include <iostream>                                                                
using namespace std;                                                               
int main() {                                                                       
    cout << A<int>::b << endl;                                                     
    return 0;                                                                      
}   

我相信标准的这句话可能会澄清任何疑问

[注意:一旦定义了静态数据成员,即使没有创建其类的对象,它仍然存在。[ 示例:在上面的例子中,即使程序没有创建类进程的对象,run_chain 和运行也存在。 — 结束示例 ] — 尾注 ]

这是标准的相关部分,可以确认您的怀疑。

除非类模板专用化已显式实例化 (14.7.2( 或显式专用化 (14.7.3(,否则当在需要完全定义的对象类型的上下文中引用专用化时,或者当类类型的完整性影响程序的语义时,将隐式实例化类模板专用化。类模板专用化的隐式实例化会导致类成员功能、成员类、静态数据成员和成员模板的定义或默认参数的隐式实例化,但不是类成员函数的定义或默认参数的隐式实例化;它导致成员匿名工会定义的隐式实例化。除非类模板或成员模板的成员已被显式实例化或显式专用化,否则当在需要成员定义的上下文中引用专用化时,将隐式引入成员的专用化;特别是,静态数据成员的初始化(以及任何关联的副作用(不会发生,除非静态数据成员本身的使用方式要求存在静态数据成员的定义。

我认为我以粗体突出显示的两个部分可以解决您的问题。显然,这种行为的原因是,如果没有给出明确的专用化,编译器就无法决定代码应该执行多少次(无限可能的类型(