Maison >développement back-end >C++ >Pourquoi l'initialisation des membres statiques dans les classes basées sur un modèle se comporte-t-elle différemment ?

Pourquoi l'initialisation des membres statiques dans les classes basées sur un modèle se comporte-t-elle différemment ?

DDD
DDDoriginal
2024-10-28 08:57:02735parcourir

 Why Does Static Member Initialization in Templated Classes Behave Differently?

Complications de l'initialisation des membres statiques dans les classes basées sur des modèles

L'initialisation des membres statiques en C est une technique largement utilisée, mais elle peut devenir complexe lorsqu'il s'agit de classes modélisées. Dans les classes sans modèle, une structure d'assistance imbriquée peut être utilisée pour l'initialisation, mais cette approche ne suffit pas lorsque la classe englobante est basée sur un modèle.

Considérez l'exemple simplifié suivant :

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

Comportement attendu :

Lorsque [1] n'est pas commenté et [2] est commenté, nous nous attendons à ce que B::mB soit initialisé à "Bonjour, je suis B." . Cependant, cela ne se produit pas.

Comportement réel :

  • Avec [1] et [2] commentés : Aucun effet secondaire se produire.
  • Avec [1] non commenté : B::getB() renvoie une chaîne vide.
  • Avec [1] et [2 ] non commenté : B::mB est correctement initialisé.
  • Avec [1] commenté et [2] non commenté : Un défaut de segmentation se produit lors de l'initialisation statique.

Raison de l'écart :

Selon la norme ISO/IEC C 2003, le membre du modèle est implicitement instancié lorsqu'il est référencé dans un contexte qui nécessite sa définition pour exister. Toutefois, l’initialisation des données membres statiques (et tous les effets secondaires associés) ne se produisent que lorsque les données membres statiques sont explicitement utilisées. Cela signifie que si un membre de modèle est uniquement référencé dans des modèles non instanciés ou dans d'autres contextes qui ne nécessitent pas son instanciation complète, ses données membres statiques ne seront pas initialisées.

Dans l'exemple, B:: getB() nécessite que B::mB existe, mais cela force uniquement l'instanciation de la déclaration du modèle membre, pas sa définition (y compris l'initialiseur). En revanche, B::getHelper() nécessite la définition de B::mInit car il renvoie une référence à celui-ci.

Solution :

La norme interdit que les définitions des membres de données statiques de modèles de classe explicitement spécialisés aient une initialisation ordonnée, tandis que les autres membres de données statiques de modèles de classe ont une initialisation non ordonnée. Pour garantir un ordre d'initialisation cohérent, il faut utiliser des spécialisations explicites.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn