簡體   English   中英

g ++和clang ++使用靜態成員的遞歸初始化的不同行為

[英]g++ and clang++ different behaviour with recursive initialization of a static member

給出以下代碼:

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

在遞歸初始化模板struct foo的靜態成員value的地方,我從g ++獲得不同的輸出:

3 2 1 0

從clang ++:

1 1 1 0

所以似乎g ++使用foo<N-1u>::value的初始化foo<N>::value遞歸初始化foo<N-1u>::value ,其中clang ++對foo<N-1u>::value使用零。

兩個問題:

  1. 前面的代碼是合法的還是以某種方式未定義的行為?
  2. 如果前面的代碼是合法的,誰是對的:g ++或clang ++?

它沒有具體說明。 兩個編譯器都是對的。

以下是cppreference“initialization”的相關部分。

靜態初始化

對於所有其他非本地靜態和線程局部變量,將進行零初始化

因此,對於所有這些變量,程序加載時它們為零。 然后:

動態初始化

完成所有靜態初始化后 ,在以下情況下會發生非局部變量的動態初始化:

1)無序動態初始化,僅適用於(靜態/線程局部)類模板靜態數據成員和......未明確專門化的。

這些變量符合標准。 然后它說:

對於所有其他動態初始化,這些靜態變量的初始化是不確定的。

這意味着任何初始化序列都可以。 這兩種編譯器是正確的。

為避免此問題,請使用constexpr強制執行“常量初始化”。

它是未指定的

您正在使用一個構造 ,您可以在其中引用變量定義 - 可能有點類似於說int i = i-1 在clang的情況下,它只是使用通用模板定義

template <std::size_t N>
struct foo
  { static std::size_t value; };//without specialization this will be ZERO initialized

因為它沒有像普通模板類或函數那樣看到 '本身'(與gcc情況相反)。

總結一下:

1)合法

2)未指定

為了避免問題,請使用並專門化類模板。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM