Puisqu'il s'agit d'une copie d'un temporaire, il peut et probablement sera optimisé
Le mot clé ici est probablement . La norme autorise, mais n'oblige pas, un compilateur à optimiser la copie. Si certains compilateurs autorisaient ce code (optimisé), mais que d'autres le rejetaient (non optimisé), cela serait très incohérent.
La norme prescrit donc une manière cohérente de traiter ce problème : chacun doit vérifier que le constructeur de copie est accessible, qu'il l'utilise ensuite ou non.
L'idée est que tous les compilateurs doivent soit accepter le code, soit le rejeter. Sinon, il ne sera pas portable.
Autre exemple, considérez
A a;
B b;
A a1 = a;
A a2 = b;
Il serait tout aussi incohérent de permettre a2
mais interdit a1
quand A
Le constructeur de la copie est privé.
Nous pouvons également voir dans le texte de la norme que les deux méthodes d'initialisation d'un objet de classe étaient destinées à être différentes (8.5/16) :
Si l'initialisation est une initialisation directe, ou si c'est une initialisation par copie où la version cv-unqualifiée du type source est la même classe que, ou une classe dérivée de, la classe de la destination, les constructeurs sont considérés. Les constructeurs applicables sont énumérés (13.3.1.3), et le meilleur est choisi par résolution de surcharge (13.3). Le constructeur ainsi sélectionné est appelé pour initialiser l'objet, avec l'expression initialisatrice ou liste d'expressions comme argument(s). Si aucun constructeur ne s'applique, ou si la résolution de la surcharge est ambiguë, l'initialisation est mal formée.
Sinon (c'est-à-dire pour les autres cas d'initialisation par copie), les séquences de conversion définies par l'utilisateur qui peuvent convertir le type source en type destination ou (lorsqu'une fonction de conversion est utilisée) en une classe dérivée de celui-ci sont énumérées comme décrit en 13.3.1.4, et la meilleure est choisie par résolution de surcharge (13.3). Si la conversion ne peut pas être faite ou est ambiguë, l'initialisation est mal formée. La fonction sélectionnée est appelée avec l'expression d'initialisation comme argument ; si la fonction est un constructeur, l'appel initialise un temporaire de la version cv-unqualifiée du type de destination. Le temporaire est une prvalue. Le résultat de l'appel (qui est le temporaire pour le cas du constructeur) est ensuite utilisé pour initialiser directement, selon les règles ci-dessus, l'objet qui est la destination de l'initialisation par copie. Dans certains cas, une implémentation est autorisée à éliminer la copie inhérente à cette initialisation directe en construisant le résultat intermédiaire directement dans l'objet à initialiser ; voir 12.2, 12.8.
La différence est que l'initialisation directe utilise directement les constructeurs de la classe construite. Avec l'initialisation par copie, d'autres fonctions de conversion sont prises en compte et celles-ci peuvent produire un temporaire qui doit être copié.