Maison >développement back-end >C++ >Pourquoi le constructeur de déplacement n'est-il pas appelé dans C 11 lorsque l'élision de copie est activée ?

Pourquoi le constructeur de déplacement n'est-il pas appelé dans C 11 lorsque l'élision de copie est activée ?

DDD
DDDoriginal
2024-11-06 09:46:02306parcourir

Why Is the Move Constructor Not Called in C  11 When Copy Elision Is Enabled?

Constructeur de déplacement C 11 non appelé, constructeur par défaut préféré

Lorsque vous travaillez avec des classes en C, il est prévu que les constructeurs de déplacement soient utilisés pour transfert efficace des ressources. Cependant, dans certains cas, le constructeur par défaut peut être choisi de manière inattendue.

Énoncé du problème

Considérez la classe suivante :

<code class="cpp">class X {
public:
    explicit X(char* c) { cout << "ctor" << endl; init(c); }
    X(X& lv)  { cout << "copy" << endl;  init(lv.c_); }
    X(X&& rv) { cout << "move" << endl;  c_ = rv.c_; rv.c_ = nullptr; }

    const char* c() { return c_; }

private:
    void init(char* c) { c_ = new char[strlen(c) + 1]; strcpy(c_, c); }
    char* c_;
};</code>

Avec l'exemple d'utilisation :

<code class="cpp">X x("test");
cout << x.c() << endl;
X y(x);
cout << y.c() << endl;
X z(X("test"));
cout << z.c() << endl;</code>

Le résultat attendu est :

ctor
test
copy
test
ctor move test

Cependant, la dernière ligne affiche de manière inattendue "ctor" au lieu de "move".

Explication

Selon la norme C 11, les constructeurs de mouvements doivent être appelés dans certaines situations. Dans ce cas, un déplacement devrait se produire lors de la construction de z avec X("test"). Cependant, le constructeur par défaut est appelé à la place.

Ce comportement est dû à l'élision de copie, une technique d'optimisation qui permet au compilateur de construire directement un temporaire dans une cible sans effectuer d'opération de copie ou de déplacement. Cette optimisation s'applique dans les cas où le compilateur détermine que l'opération de copie/déplacement est inutile et peut être supprimée.

Dans le scénario donné, le compilateur considère le X("test") temporaire comme candidat à l'élision de copie, car il est automatiquement créé et détruit au sein de la même expression. Par conséquent, il omet l'opération de déplacement et construit z directement en utilisant les données du temporaire, ce qui entraîne l'appel au constructeur par défaut.

Conclusion

L'élision de copie peut conduire à des erreurs inattendues. comportement lorsque vous travaillez avec des constructeurs de déplacement, car cela peut empêcher le constructeur de déplacement d'être invoqué dans les situations où il est attendu. Les compilateurs peuvent appliquer l'élision de copie en fonction de leurs heuristiques d'optimisation, qui peuvent varier selon les compilateurs et les paramètres d'optimisation. Il est important d'être conscient de l'élision de copie et de son impact potentiel sur le comportement du programme.

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