ホームページ  >  記事  >  バックエンド開発  >  静的メンバーを含むテンプレート化されたクラスで `B::getB()` が `mB` の初期化に失敗するのはなぜですか?

静的メンバーを含むテンプレート化されたクラスで `B::getB()` が `mB` の初期化に失敗するのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-10-31 05:59:02456ブラウズ

 Why Does `B::getB()` Fail to Initialize `mB` in Templated Classes with Static Members?

テンプレートでの静的メンバーの初期化: 詳細

C では、入れ子になったヘルパー構造体の静的メンバーの初期化は、通常、テンプレート化されていないクラスでは問題なく機能します。ただし、囲んでいるクラスがテンプレート化されている場合、メイン コードでヘルパー オブジェクトにアクセスしないと、潜在的な問題が発生します。

テンプレート化されたクラスの問題

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

<code class="cpp">struct A
{
    struct InitHelper
    {
        InitHelper()
        {
            A::mA = "Hello, I'm A.";
        }
    };
    static std::string mA;
    static InitHelper mInit;

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

template<class T>
struct B
{
    struct InitHelper
    {
        InitHelper()
        {
            B<T>::mB = "Hello, I'm B.";
        }
    };
    static std::string mB;
    static InitHelper mInit;

    static const std::string& getB() { return mB; }
    static InitHelper& getHelper(){ return mInit; }
};</code>

ここで、ネストされた InitHelper は、A の静的メンバー mA と B の mB を初期化します。

問題は、テンプレート化されたクラス B のメンバーを初期化しようとすると発生します。 getB メソッドを使用する以下に示すように、mB の初期化はトリガーされません:

<code class="cpp">std::cout << "B = " << B<int>::getB() << std::endl;

これは、ISO/IEC C 2003 標準 (14.7.1) に従って、静的データ メンバーの初期化のみが発生するために発生します。メンバー自体がその定義を必要とする方法で使用される場合。この場合、mB はテンプレート化されたクラスの getB() メソッドでのみ参照されるため、コンパイラーはその定義を暗黙的にインスタンス化しません。

暗黙的なインスタンス化と明示的な特殊化

コンパイラーの説明動作を理解するには、暗黙的なインスタンス化の概念を明確にすることが重要です。テンプレート内の静的データ メンバーの場合、暗黙的なインスタンス化では宣言はインスタンス化されますが、定義はインスタンス化されません。実際の初期化 (コンストラクター呼び出し) は、静的データ メンバーがその定義 (割り当てなど) を必要とする方法で使用される場合にのみ発生します。

一方、明示的な特殊化では、名前空間またはクラスでの明示的な宣言が使用されます。初期化を命令したもの。つまり、特殊な静的データ メンバーは、そのクラス テンプレートのインスタンス化の前に常に初期化されます。

答え

特定のコード例では、B::getHelper() を呼び出します。 getHelper が mInit への参照を返すため、mB と mInit の両方の初期化がトリガーされます。これには InitHelper が存在する必要があります。

ただし、初期化の順序に依存する動作は未定義です。正しい解決策は、クラス B の静的データ メンバー mInit を明示的に特殊化することです。これにより、ヘルパー オブジェクトが常に作成され、その後の B のインスタンス化でその静的データ メンバーが正しく初期化されることが保証されます。

結論

要約すると、C テンプレートでの静的メンバーの初期化には慎重な検討が必要です。暗黙的なインスタンス化では、宣言のみがインスタンス化され、定義はインスタンス化されません。順序付けされた信頼性の高い初期化を実現するには、静的データ メンバーを含むテンプレート クラスを扱うときに明示的な特殊化を考慮する必要があります。

以上が静的メンバーを含むテンプレート化されたクラスで `B::getB()` が `mB` の初期化に失敗するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。