[英]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
使用零。
兩個問題:
它沒有具體說明。 兩個編譯器都是對的。
以下是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)未指定
為了避免問題,請使用constexpr並專門化類模板。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.