【问题标题】:When do constructors of static members of template classes get called in C++?什么时候在 C++ 中调用模板类的静态成员的构造函数?
【发布时间】:2011-10-21 00:58:19
【问题描述】:

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

以下程序的输出应该是什么? (注意我使用 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;
}

我认为输出应该是:

Hello I am B from A
Hello I am B from Atempl

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

Hello I am B from A

如果我添加行

template class Atempl<int>;

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

【问题讨论】:

    标签: c++ templates constructor static-members


    【解决方案1】:

    在类模板中,当执行隐式实例化时,成员会按需实例化。由于代码没有使用静态成员,因此甚至没有在整个应用程序中实例化。

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

    如果没有显式实例化,您可以执行类似B* p = &amp;Atempl&lt;int&gt;::b_;(或静态成员的任何其他用途)之类的操作来触发实例化。

    【讨论】:

    • 这似乎是正确的。这是标准的相关部分吗?标准说(在 ISO/IEC 14882:1998(E) 的第 14.7.1 节中)...特别是,除非静态数据成员的初始化(以及任何相关的副作用)不会发生数据成员本身的使用方式要求静态数据成员的定义存在。
    • @Manish: Right §14.7.1/1 包含该引用,但在下面的几段中还有另一个引用:§14.7.1/7 类模板的隐式实例化确实不会导致该类的任何静态数据成员被隐式实例化。
    • 啊,完美。感谢您的帮助。
    【解决方案2】:

    当类模板模板的静态成员被初始化时 未指定。实际上,除非您实际使用静态成员,否则它 不应该被实例化,所以永远不要被初始化。如果你 显式实例化模板,你强制实例化所有 的成员,这反过来又强制初始化(但我认为 确切的初始化时间仍未指定)。

    【讨论】:

    • +1 总体而言,关于实例化的具体细节,我相信在 §14.6.4.1/1 中:对于类的 [...] 或静态数据成员模板,[...(此处不适用的情况)否则,] 这种特化的实例化点紧跟在命名空间范围声明或引用特化的定义之后。 为简洁起见,我删除了内容(否则它不适合评论,但这种情况在第一个 [...] 中不考虑,属于 Otherwise 情况。
    • 但是静态数据成员的实例化点对初始化顺序没有任何影响。在这方面,实例化成员的行为与普通类成员不同。 (这样做的原因当然是它可能在几个不同的源文件中被实例化,当然,初始化仍然只会发生一次。)
    • 对,我把instantiation误解为initialization了。很抱歉造成混乱。
    【解决方案3】:

    C++ 运行时在进程启动之后和调用main() 之前的某个时间调用它们。 “常规”类和类模板实例之间没有区别。构造函数的调用顺序是不确定的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 2020-12-22
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多