g++ 和 clang++ 静态成员递归初始化的不同行为

2024-03-25

给出以下代码:

#include <iostream>

template <std::size_t N>
struct foo
 { static std::size_t value; };

template <>
std::size_t foo<0>::value = 0u;

template <size_t N>
std::size_t foo<N>::value = 1u + foo<N - 1u>::value;

int main()
 {
   std::cout
      << foo<3u>::value << ' '
      << foo<2u>::value << ' '
      << foo<1u>::value << ' '
      << foo<0u>::value << std::endl;
 }

静态成员在哪里value模板结构体的foo是递归初始化的,我从 g++ 得到不同的输出:

3 2 1 0

以及来自 clang++ 的:

1 1 1 0

所以看起来 g++ 初始化了foo<N>::value递归地使用初始化值foo<N-1u>::value其中 clang++ 使用零foo<N-1u>::value.

两个问题:

  1. 前面的代码是合法的还是以某种方式存在未定义的行为?
  2. 如果前面的代码是合法的,那么谁是对的:g++ 还是 clang++?

这是未指定的。两个编译器都是对的。

以下是来自的相关片段cppreference“初始化” https://en.cppreference.com/w/cpp/language/initialization.

静态初始化

对于所有其他非局部静态和线程局部变量,进行零初始化

因此,对于所有这些变量,当程序加载时它们为零。然后:

动态初始化

全部静态初始化完成后,非局部变量的动态初始化发生在以下情况 情况:

1)无序动态初始化,仅适用于 (静态/线程本地)类模板静态数据成员和......没有明确专门化。

这些变量符合标准。然后它说:

此类静态变量的初始化是不确定顺序的 关于所有其他动态初始化......

这意味着任何初始化顺序都可以。两个编译器都是正确的。

为了避免该问题,请使用constexpr强制执行“常量初始化”。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

g++ 和 clang++ 静态成员递归初始化的不同行为 的相关文章

随机推荐