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!