什么时候在C++中调用模板类的静态成员的构造函数?

Man*_*ish 9 c++ templates constructor static-members

关于何时调用普通类的静态成员的构造函数,有大量信息.但是,我看到一些关于模板类的奇怪行为.

以下程序的输出应该是什么?(注意我使用printf来避免任何静态初始化命令与std :: cout的混淆并发症.)

#include <iostream>

class B {
public:
  B(const std::string &s) { printf("Hello I am B from %s\n", s.c_str()); }
};

template<typename T>
class Atempl {
public:
  static B b_;
};

class A {
public:
  static B b_;
};

template<typename T>
B Atempl<T>::b_("Atempl");
B A::b_("A");

class C : public Atempl<int> {
};

int main(int argc, const char *argv[]) {
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我认为输出应该是:

Hello I am B from A
Hello I am B from Atempl
Run Code Online (Sandbox Code Playgroud)

但是使用FreeBSD 7.3上的g ++ 4.3,我得到:

Hello I am B from A
Run Code Online (Sandbox Code Playgroud)

如果我添加该行

template class Atempl<int>;
Run Code Online (Sandbox Code Playgroud)

一切都很好,我得到了预期的输出.问题是,为什么类C的声明不算作模板Atempl的实例化并导致B的构造函数被调用?这是标准的一部分还是g ++ 4.3中的错误?

Dav*_*eas 10

在类模板中,执行隐式实例化时,会根据需要实例化成员.由于代码不使用静态成员,因此甚至不在整个应用程序中实例化.

当您进行显式实例化时,将实例化整个类及其所有成员,并包含静态成员变量,然后对其进行初始化并获得预期结果.

如果没有显式实例化,您可以执行类似B* p = &Atempl<int>::b_;(或任何其他静态成员的使用)来触发实例化.