首页 > 解决方案 > 为什么模板的静态成员在稍后在同一翻译单元中定义的对象之后初始化?

问题描述

考虑以下(人工)示例:

#include <iostream>

int f() {
  return 42;
}

template <typename T>
struct S {
  static int I;
};

template <typename T>
int S<T>::I = f();

template <typename T>
int g() {
  return S<T>::I;
}

int global = g<int>();

int main() {
  std::cout << global << std::endl;
}

它在使用 gcc 4.8.4 编译并运行时打印 0:

$ g++ test.cc
$ ./a.out
0

这表明在初始化 forglobal之前运行动态初始化 for S<T>::I>。但是,根据this SO answer

在同一个翻译单元中定义的对象(通常是 .cpp 文件)按照它们的定义顺序进行初始化

为什么动态初始化在 forglobal之前运行S<T>::I>而不是按照它们的定义顺序运行,是否可以在global之后强制初始化?

标签: c++templatesinitialization

解决方案


由于 的初始化S<T>::I是无序的,因此 的值S<int>::I可以是 0(如果在 之后初始化global)或 42(如果在 之前初始化global)。

虽然您不能强制编译器在I之前进行初始化global,但只要稍微更改您的代码,您就可以使用用于对不同翻译单元中定义的静态变量进行排序的相同方法。通过更改I为将其值存储在内部静态变量中的函数,您可以确保它在global.

template <typename T>
struct S {
  static int I() {
    static int i = f();
    return i;
  }
};

template <typename T>
int g() {
  return S<T>::I();
}

推荐阅读