9
votes

Pourquoi le constructeur de copie n'est pas appelé pour copier l'objet temporaire sur le nouvel objet défini

#include <iostream>
using namespace std;

class Y {
public:
    Y(int ) {
        cout << "Y(int)\n";
    }
    Y(const Y&) {
        cout << " Y(const Y&)\n";
    }
};

int main() {
    Y obj1 = 2; // Line 1
}
Output: Y(int)Expected Output: Y(int)
                 Y(const Y&)Question> Based on my understanding, Line 1 will first create a temporary object Y(2), and then assign the temporary object to obj1. Thus, I expect both Y(int) and Y(const Y&) are called. But the output from vs2010 only reports the first one(i.e. Y(int)). Why?

0 commentaires

3 Réponses :


10
votes

Pourquoi?

Parce que dans certaines conditions (spécifié par le paragraphe 12.8 / 31 de l'alinéa 12.8 / 31 de la norme C ++ 11), les appels au constructeur de copie ou du constructeur de déplacement peuvent être élus, même si ces fonctions spéciales (ou le destructeur) ont des effets secondaires:

Cette élision de copie / déplacement opérations, appelées élision de copie, est autorisée dans les circonstances suivantes (qui peuvent être combinées à Éliminer plusieurs copies):

- [...]

- Lorsqu'un objet de classe temporaire qui n'a pas été lié à une référence (12.2) serait copié / déplacé à un objet de classe avec le même type CV-non qualifié, l'opération de copie / déplacement peut être omise par construire l'objet temporaire directement dans la cible de la copie omise / déplacement

- [...]

Ceci est la seule exception à la règle dite " as-si ", qui contraint normalement le type de transformations (optimisations) qu'un compilateur peut effectuer sur un programme afin de préserver sa comportement observable.

avis, que le mécanisme ci-dessus s'appelle copier élision - même lorsqu'il est en fait un appel au constructeur de déplacement qui est élu.


0 commentaires

3
votes

2 commentaires

Voir la réponse de Stefano pour une discussion ultérieure (Andy's est correcte). Un explicite provoquant une erreur signifie qu'ils ne sont nullement équivalents.


L'initialisation de la copie n'est pas équivalente à l'initialisation directe. Le premier est conceptuellement réalisé en construisant un temporaire à partir de l'expression d'initialisation ( 2 ), puis de construire ou de construire une copie obj1 de ce temporaire. Cependant, le compilateur est autorisé à élier cet appel au constructeur de déplacement ou au constructeur de copie par 12,8 / 31 (voir ma réponse)



4
votes

Ceci est parce que le constructeur n'a qu'un seul paramètre et que ce n'est pas marqué explicite code>, de sorte que le compilateur tourne automatiquement: xxx pré>

dans: p>

explicit Y(int ) {
    cout << "Y(int)\n";
}


2 commentaires

Le fait que explicite provoque une erreur de compilateur signifie qu'il ne tourne pas par magiquement = 2 dans (2) . Tout explicite est empêchant les conversions implicites sur votre type.


"Pour empêcher ce comportement [...] et la compilation échouera dans votre cas."