Heim >Backend-Entwicklung >C++ >Warum verhält sich die Initialisierung statischer Elemente in Klassen mit Vorlagen anders?

Warum verhält sich die Initialisierung statischer Elemente in Klassen mit Vorlagen anders?

DDD
DDDOriginal
2024-10-28 08:57:02729Durchsuche

 Why Does Static Member Initialization in Templated Classes Behave Differently?

Komplikationen bei der statischen Member-Initialisierung in Vorlagenklassen

Die statische Member-Initialisierung in C ist eine weit verbreitete Technik, deren Handhabung jedoch komplex werden kann Klassen mit Vorlagen. In nicht auf Vorlagen basierenden Klassen kann eine verschachtelte Hilfsstruktur zur Initialisierung verwendet werden, aber dieser Ansatz greift nicht, wenn die umschließende Klasse auf Vorlagen basiert.

Betrachten Sie das folgende vereinfachte Beispiel:

<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>

Erwartetes Verhalten:

Wenn [1] unkommentiert und [2] kommentiert ist, würden wir erwarten, dass B::mB mit „Hallo, ich bin B“ initialisiert wird. . Dies geschieht jedoch nicht.

Tatsächliches Verhalten:

  • Mit [1] und [2] kommentiert:Keine Nebenwirkungen auftreten.
  • Mit [1] unkommentiert: B::getB() gibt einen leeren String zurück.
  • Mit [1] und [2 ] unkommentiert: B::mB ist korrekt initialisiert.
  • Mit [1] kommentiert und [2] unkommentiert: Während der statischen Initialisierung tritt ein Segmentierungsfehler auf.

Grund für die Diskrepanz:

Gemäß dem ISO/IEC C 2003-Standard wird das Vorlagenmitglied implizit instanziiert, wenn es in einem Kontext referenziert wird, der seine Definition erfordert existieren. Die Initialisierung des statischen Datenelements (und alle damit verbundenen Nebenwirkungen) erfolgt jedoch nur, wenn das statische Datenelement explizit verwendet wird. Das bedeutet, dass, wenn auf ein Vorlagenmitglied nur in nicht instanziierten Vorlagen oder in anderen Kontexten verwiesen wird, die keine vollständige Instanziierung erfordern, seine statischen Datenmitglieder nicht initialisiert werden.

Im Beispiel B:: Für getB() muss B::mB vorhanden sein, dies erzwingt jedoch nur die Instanziierung der Member-Template-Deklaration, nicht deren Definition (einschließlich des Initialisierers). Im Gegensatz dazu erfordert B::getHelper() die Definition von B::mInit, da es einen Verweis darauf zurückgibt.

Lösung:

Der Standard schreibt vor, dass Definitionen von explizit spezialisierten statischen Datenelementen der Klassenvorlage eine geordnete Initialisierung haben, während andere statische Datenelemente der Klassenvorlage eine ungeordnete Initialisierung haben. Um eine konsistente Initialisierungsreihenfolge sicherzustellen, müssen explizite Spezialisierungen verwendet werden.

Das obige ist der detaillierte Inhalt vonWarum verhält sich die Initialisierung statischer Elemente in Klassen mit Vorlagen anders?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn