g ++和clang ++的不同行为与静态成员的递归初始化 [英] g++ and clang++ different behaviour with recursive initialization of a static member

查看:70
本文介绍了g ++和clang ++的不同行为与静态成员的递归初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

#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;
 }

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

where the static member value of the template struct foo is recursively initialized, I get different outputs from g++:

3 2 1 0

和从clang ++:

and from clang++:

1 1 1 0

似乎g ++使用 foo< N-1u> :: value 的初始化值递归地初始化 foo< N> :: value ,其中clang ++对 foo< N-1u> :: value .

So seem that g++ initializes foo<N>::value recursively using the initialized value of foo<N-1u>::value where clang++ uses zero for foo<N-1u>::value.

两个问题:

  1. 前面的代码是合法的还是某种程度上的未定义行为?
  2. 如果前面的代码是合法的,谁是对的:g ++或clang ++?

推荐答案

未指定.两种编译器都是正确的.

It is unspecified. Both compilers are right.

以下是 cppreference初始化" 中的相关内容.

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

For all other non-local static and thread-local variables, Zero initialization takes place

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

So for all these variables, they are zero when the program loads. Then:

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

After all static initialization is completed, dynamic initialization of non-local variables occurs in the following situations:

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

1) Unordered dynamic initialization, which applies only to (static/thread-local) class template static data members and ... that aren't explicitly specialized.

并且这些变量符合条件.然后它说:

And these variables match the criteria. And then it says:

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

Initialization of such static variables is indeterminately sequenced with respect to all other dynamic initialization ....

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

Which means that any sequence of initialization is fine. Both compilers are correct.

为避免该问题,请使用 constexpr 强制执行恒定初始化".

To avoid the issue use constexpr to force a "constant initialization" instead.

这篇关于g ++和clang ++的不同行为与静态成员的递归初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆