如果未使用静态 menber,则静态成员变量是否在模板类中初始化
Is static member variable initialized in a template class if the static menber is not used?
如果不使用静态成员,静态成员变量是否在模板类中初始化?我用它来注册类型。
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(,否则当在需要完全定义的对象类型的上下文中引用专用化时,或者当类类型的完整性影响程序的语义时,将隐式实例化类模板专用化。类模板专用化的隐式实例化会导致类成员功能、成员类、静态数据成员和成员模板的定义或默认参数的隐式实例化,但不是类成员函数的定义或默认参数的隐式实例化;它导致成员匿名工会定义的隐式实例化。除非类模板或成员模板的成员已被显式实例化或显式专用化,否则当在需要成员定义的上下文中引用专用化时,将隐式引入成员的专用化;特别是,静态数据成员的初始化(以及任何关联的副作用(不会发生,除非静态数据成员本身的使用方式要求存在静态数据成员的定义。
我认为我以粗体突出显示的两个部分可以解决您的问题。显然,这种行为的原因是,如果没有给出明确的专用化,编译器就无法决定代码应该执行多少次(无限可能的类型(
- 列表初始化是否将原子初始化为零
- 使用函数声明进行函数指针初始化 - 是否可能
- 值初始化是否适用于原子对象?
- 聚合的值初始化是否使用其成员的默认初始值设定项?
- C 11联合会的空列表初始化 - 是否保证可以初始化工会的全长
- 找出静态初始化是否结束
- 非本地非内联变量的初始化:是否严格在"main()"函数调用之前进行
- 空字符数组的初始化是否有效
- 变量零初始化-是否有未定义的行为
- 0-原子的初始化是否保证将值成员设置为0
- POD 类对象初始化是否需要构造函数
- 在C++中使用类似 c 的初始化或构造函数初始化是否被认为更好
- 类内成员初始化是否删除赋值运算符
- C++11;非静态数据成员初始化是否可以访问其他数据成员
- 列表初始化是否为隐式转换
- 复制列表初始化是否在概念上调用复制 ctor
- 如何测试/验证零初始化是否发生
- C++默认初始化是否保留先前的零初始化
- 使用新结构体进行聚合初始化是否有效
- 检测CRT初始化是否在注入过程中完成