Maison > développement back-end > C++ > Pourquoi mon constructeur de déplacement C 11 n'est-il pas appelé dans ce cas ?

Pourquoi mon constructeur de déplacement C 11 n'est-il pas appelé dans ce cas ?

Susan Sarandon
Libérer: 2024-11-05 01:49:02
original
533 Les gens l'ont consulté

Why Doesn't My C  11 Move Constructor Get Called in This Case?

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

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>
Copier après la connexion

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>
Copier après la connexion

La sortie est :

ctor
test
copy
test
ctor   <-- why not move?
test
Copier après la connexion

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 ?

Question

Le constructeur de mouvements doit-il être appelé selon la norme C 11 ? Si oui, pourquoi n'est-il pas appelé ?

Réponse

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 une fonction avec un type de retour classe, si l'expression de retour est une automatique non volatile objet avec le même type que le type de retour.
  • Dans une expression de lancement, si l'opérande est un objet automatique non volatile dont la portée ne s'étend pas au-delà du bloc try englobant.
  • Lorsqu'un objet de classe qui n'a pas été lié à une référence serait copié/déplacé vers un objet de classe du même type.
  • Lorsque le gestionnaire d'exception déclare un objet du même type comme objet d'exception en traitant la déclaration d'exception comme un alias.

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal