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>
Et son 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>
La sortie est :
ctor test copy test ctor <-- why not move? test
Dans VS2010, en utilisant les paramètres par défaut, on pourrait s'attendre à ce que le dernier objet (z) soit construit par déplacement au lieu d'être construit par défaut. L'utilisation de X z( move(X("test")) ) donne le résultat attendu : ctor move test. Serait-ce un cas de NRVO ?
Le constructeur de mouvements doit-il être appelé selon la norme C 11 ? Si oui, pourquoi n'est-il pas appelé ?
Le comportement observé est dû à l'élision de copie. Le compilateur peut directement construire un temporaire dans une cible dans laquelle il doit être copié/déplacé, omettant ainsi les appels de constructeur et de destructeur de copie/déplacement.
Les situations dans lesquelles l'élision de copie peut être appliquée sont décrites au §12.8. 32 de la norme C 11 :
Dans ce cas, le compilateur est capable d'éluder l'opération de copie ou de déplacement entre le X("test") temporaire et la cible z, ce qui entraîne le comportement observé.
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!