initialisation: parenthèse vs signe égal

Dupliquer possible:
Existe-t-il une différence en C ++ entre l’initialisation de copie et l’initialisation d’affectation?

Quelle est la différence entre

T a(b); 

et

 T a = b; 

et

 T a = T(b); 

?

 T a( b ); 

est une initialisation directe , à moins qu’elle n’parsing une déclaration de fonction, auquel cas c’est une déclaration de fonction.

 T a = b; 

Ceci correspond à l’initialisation de la copie , ce qui signifie qu’il fonctionne comme si un object temporaire était construit du côté droit et qu’un object est ensuite construit ou, en C ++ 11 et ultérieur, éventuellement déplacé, à partir de cet object temporaire.

Le compilateur est libre d’éliminer (supprimer) le temporaire + la copie / le déplacement chaque fois qu’il le peut, mais un constructeur de copie ou de déplacement, quel que soit celui qui serait utilisé logiquement, doit toujours être accessible et non explicit .

Par exemple, en C ++ 03, vous ne pouvez pas copier-initialiser un std::ossortingngstream , car il ne possède pas de constructeur de copie. En C ++ 11, vous pouvez copier-initialiser un ossortingngstream si l’initialiseur est temporaire, ce qui aboutit ensuite à une construction de déplacement logique (qui sera toutefois généralement supprimée et optimisée). Par exemple, cette déclaration d’initialisation de copie,

 ossortingngstream s = ossortingngstream( "blah" ); 

… Ne comstack pas en tant que C ++ 03, car en C ++ 03, l’initialisation de la copie appelle le constructeur de copie de la classe, qui n’existe pas. Cependant, il est compilé en C ++ 11, car en C ++ 11, l’initialisation de la copie appelle le constructeur du déplacement. Et bien que (pour conserver l’illusion d’être un stream), un stream std::ossortingngstream ne puisse pas être copié directement, il peut être déplacé.

Autre différence: en C ++ 03, seule la syntaxe d’initialisation de copie prend en charge l’initialiseur d’ accolades , que vous pouvez utiliser en C ++ 03 lorsque T est un type agrégat tel qu’un tableau brut. En C ++ 11, la notation des accolades a été étendue et généralisée sous la forme d’ une syntaxe d’initialisation uniforme ; elle peut donc être utilisée également avec une initialisation directe. Et si la déclaration d’initialisation directe suivante,

 int v[]{ 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 }; 

… Ne comstack pas en tant que C ++ 03, mais comstack en tant que C ++ 11 et versions ultérieures.

La syntaxe d’initialisation = copy est la syntaxe d’initialisation d’origine à partir de C.

Et en C ++ 11 et std::ossortingngstream ultérieures, en raison de la sémantique de déplacement, il peut être utilisé dans un éventail de cas beaucoup plus large qu’en C ++ 03, comme avec un std::ossortingngstream .

 T a(b); 

Appelle le constructeur de a qui accepte b . (Si b est du même type, le constructeur de copie est appelé).

 T a = b; 

un object temporaire de type T est créé pour être construit par b . Ensuite, le constructeur de copie est appelé ( = n’est pas une affectation dans ce cas et dans le cas suivant!).

 T a = T(b); 

Comme ci-dessus! sauf que nous avons explicitement construit un object temporaire.

Notez que la norme permet l’élimination totale des copies temporaires dans les deuxième et troisième cas. De plus, si b n’est pas de type T , dans le premier cas, T n’a pas besoin de constructeur de copie. Dans les deuxième et troisième cas, même si la mise en œuvre est libre d’optimiser le tout, elle nécessite toujours un constructeur de copie accessible. Le standard IIRC appelle ceci: élision de copie .

Ce sont tous des appels de constructeurs – le signe = est simplement un sucre syntaxique. Les constructeurs qui sont appelés sont dans une certaine mesure jusqu’au compilateur.

L’opérateur = invoquera le constructeur de copie par défaut, sauf si l’opérateur = est surchargé, je crois … cela ferait une copie superficielle; affectation des mêmes valeurs de membre au premier object que l’opérateur de droite