「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > テンプレート化されたクラスでの静的メンバーの初期化の動作が異なるのはなぜですか?

テンプレート化されたクラスでの静的メンバーの初期化の動作が異なるのはなぜですか?

2024 年 11 月 14 日公開
ブラウズ:169

 Why Does Static Member Initialization in Templated Classes Behave Differently?

テンプレート クラスでの静的メンバーの初期化の複雑さ

C での静的メンバーの初期化は広く使用されている手法ですが、次のような処理を行うと複雑になる可能性があります。テンプレート化されたクラス。テンプレート化されていないクラスでは、ネストされたヘルパー構造体を初期化に使用できますが、囲んでいるクラスがテンプレート化されている場合、このアプローチは不十分です。

次の単純化された例を考えてみましょう:

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
struct B
{
    static std::string mB;
    static InitHelper mInit;

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

int main()
{
    std::cout ::getB() ::getHelper(); // [2]
}

期待される動作:

[1] がコメント化されておらず、[2] がコメント化されている場合、B::mB が " に初期化されることが期待されます。こんにちは、Bです。」ただし、これは発生しません。

実際の動作:

  • [1] と [2] のコメント付き: 副作用なし
  • [1] の場合 コメントなし: B::getB() は空の文字列を返します。
  • [1] および [2] の場合] コメントなし: B::mB は正しく初期化されています。
  • [1] がコメント化され、[2] がコメント化されていません: 静的初期化中にセグメンテーション違反が発生します。
  • ]

不一致の理由:

ISO/IEC C 2003 標準によれば、テンプレート メンバーは、その定義が必要なコンテキストで参照されると暗黙的にインスタンス化されます。存在する。ただし、静的データ メンバーの初期化 (および関連する副作用) は、静的データ メンバーが明示的に使用される場合にのみ発生します。これは、テンプレート メンバーがインスタンス化されていないテンプレート、または完全なインスタンス化を必要としない他のコンテキストでのみ参照される場合、その静的データ メンバーは初期化されないことを意味します。

この例では、B:: getB() には B::mB が存在する必要がありますが、これはメンバ テンプレート宣言のインスタンス化を強制するだけであり、その定義 (イニシャライザを含む) ではありません。対照的に、B::getHelper() は B::mInit への参照を返すため、その定義が必要です。

Solution:

この標準では、明示的に特殊化されたクラス テンプレートの静的データ メンバーの定義には順序付けされた初期化が必要ですが、他のクラス テンプレートの静的データ メンバーには順序付けされていない初期化が必要です。一貫した初期化順序を確保するには、明示的な特殊化を使用する必要があります。

最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3