首頁 >後端開發 >C++ >為什麼模板類別中的靜態成員初始化行為不同?

為什麼模板類別中的靜態成員初始化行為不同?

DDD
DDD原創
2024-10-28 08:57:02729瀏覽

 Why Does Static Member Initialization in Templated Classes Behave Differently?

模板類別中的靜態成員初始化複雜性

C 中的靜態成員初始化是一種廣泛使用的技術,但在處理時可能會變得複雜模板化的類別。在非模板化類別中,可以採用巢狀輔助結構進行初始化,但當封閉類別模板化時,這種方法就不夠了。

考慮以下簡化範例:

<code class="cpp">struct A
{
    static std::string mA;
    static InitHelper mInit;

    static const std::string& getA() { return mA; }
};
std::string A::mA;
A::InitHelper A::mInit;


template<class T>
struct B
{
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper() { return mInit; }
};
template<class T>
std::string B<T>::mB;
template<class T>
typename B<T>::InitHelper B<T>::mInit;

int main()
{
    std::cout << "A = " << A::getA() << std::endl;

    // Comment/uncomment lines to observe different behaviors
    // std::cout << "B = " << B<int>::getB() << std::endl; // [1]
    // B<int>::getHelper(); // [2]
}</code>

預期行為:

當[1] 被取消註解並且[2] 被註解時,我們期望B::mB 被初始化為「Hello, I'm B」。 。然而,這種情況不會發生。

實際行為:

  • 用[1]和[2]評論:沒有副作用
  • [1] 未註解:
  • B::getB() 傳回一個空字串。
  • [1] 和 [2 ] 未註解:
  • B::mB 已正確初始化。
  • 註 [1] 且未註記 [2]:
  • 靜態初始化期間發生分段錯誤。

差異的原因:

根據ISO/IEC C 2003 標準,在需要其定義的上下文中引用模板成員時,會隱式實例化模板成員。存在。但是,靜態資料成員初始化(以及任何相關的副作用)僅在明確使用靜態資料成員時發生。這意味著,如果範本成員僅在未實例化的範本中或在不需要其完全實例化的其他上下文中引用,則其靜態資料成員將不會被初始化。

在範例中,B:: getB() 要求B::mB 存在,但這僅強制實例化成員範本聲明,而不是其定義(包括初始值設定項)。相反,B::getHelper() 確實需要 B::mInit 的定義,因為它會傳回對其的引用。

解決方案:

此標準禁止明確專用類別模板靜態資料成員的定義進行有序初始化,而其他類別模板靜態資料成員進行無序初始化。為了確保一致的初始化順序,必須使用顯式特化。

以上是為什麼模板類別中的靜態成員初始化行為不同?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn