14

S'agit-il simplement de préférence ou existe-t-il des cas spécifiques où l'un est nécessaire par rapport à un autre? Je les variantes se référant suivantes pour l'initialisationQuand devez-vous utiliser l'initialisation directe et lors de l'initialisation de la copie?

T t(e); // direct initialization 
T t = e; // copy initialization 
+1

Qu'est-ce qu'une cession implicite? Voulez-vous dire l'opérateur d'affectation par défaut? – ybungalobill

+1

Que voulez-vous dire par "affectation implicite". –

+0

bool bValue1 = true; // affectation explicite bool bValue2 (false); // affectation implicite Cela fait-il une différence? – Mike

Répondre

19

Les noms réels des choses que vous décrivez n'est pas implicite et explicite, mais la cession:

  • Copy-initialisation: T x = a;
  • -initialisation directe : T x(a);

Ils sont pas équivalent, notamment dans les contextes où une conversion est requise, par exemple lorsque T est de type classe et a est d'un type différent (voir commentaire Alf pour des exemples de contextes qui n'impliquent même pas de conversion). Considérons le code suivant:

class Test 
{ 
public: 
    explicit Test(int i) { /* ... */ } 
}; 

int main() 
{ 
    Test t(0); // OK : calls Test::Test(int) 
    Test u = 0; // KO : constructor is marked explicit 
} 

pour paraphraser le standard (8,5/14):

  • For-initialisation directe et la copie de l'initialisation lorsque le type de source est la même que, ou une classe dérivée de , la classe de destination, constructeurs sont considérés comme
  • Pour d'autres cas-initialisation de copie, comme la deuxième ligne de main dans mon exemple, séquence de conversion définie par l'utilisateur sont considérés comme. Comme l'utilisation du constructeur Test pour la conversion implicite a été refusée par le mot clé explicit, la deuxième ligne échoue à la compilation.
+0

"Ils ne sont pas équivalents dans les contextes où une conversion est nécessaire" - il existe également d'autres situations où ils ne sont pas équivalents. –

+0

@Alf: Je n'étais pas sûr quand j'ai écrit cette phrase, mais je n'ai trouvé aucun exemple. Je pourrais me tromper sur la terminologie ici, parce que ce que je vois dans votre réponse * est * une conversion (par ce que la norme appelle un * constructeur de conversion *), et est en fait très similaire à ma réponse (sauf Je n'ai pas couvert). Qu'est-ce que je rate ? – icecrime

+1

bien, disons que 'a' est l'expression' T() '. :-) Alors la forme syntaxique d'initialisation de copie est pour la plupart équivalente à l'initialisation par défaut (sauf qu'elle peut impliquer un temporaire et une copie), tandis que la forme syntaxique d'initialisation directe donne l'interprétation comme une déclaration de fonction, "l'analyse la plus vexante". Considérons également le cas d'un constructeur de copie 'explicite'. Et en fonction de comment vaguement autorisé à penser ici, envisager initialiser les accolades bouclés. Donc, au moins 3 cas. Mais le contre-exemple direct est le constructeur 'explicit'copy. Cheers, –

10

initialisation directe comme

std::istringstream stream("blah blah"); 

est nécessaire lorsque le type en question, ici std::istringstream de la bibliothèque standard C++, ne dispose pas d'un constructeur de copie accessible.

Une initialisation copie , comme

std::istringstream stream = "blah blah"; //! NOT VALID 

nécessite un constructeur de copie accessible, car il est effectué comme si un objet temporaire est créé sur le côté droit de =, et comme si cela temporaire est ensuite utilisé initialiser la variable déclarée.

Dans l'autre sens, en C++ 98, la syntaxe d'initialisation de copie est nécessaire pour utiliser initialisateurs d'accolades. Par exemple, l'initialisation directe ne peut pas être utilisée pour initialiser un agrégat. Mais vous pouvez utiliser l'initialisation de copie avec un initialiseur d'accolades:

#include <string> 
using namespace std; 

struct Answer 
{ 
    int  nVotes; 
    string description; 
};  

int main() 
{ 
    Answer const incorrect = { 26, "they're the same!" }; 
    Answer const correct  = { -1, "nah, they're different, actually" }; 
} 

Il existe donc des différences significatives.

Je préfère généralement la syntaxe d'initialisation de copie en raison de la clarté. Mais parfois, comme indiqué ci-dessus, une initialisation directe est malheureusement nécessaire. Certaines personnes, par ex.Francis Glassborow, auteur de manuels C++, a plutôt choisi l'initialisation directe comme syntaxe d'initialisation préférée (je ne sais pas pourquoi, c'est moins clair à mes yeux, et introduit le problème de l'analyse la plus ennuyeuse), et pour eux c'est la nécessité de copier l'initialisation dans certains cas, c'est malheureux.

Vive & HTH.,

+1

Cette réponse a été écrite en 2010. Avec l'initialisation C++ 11, la syntaxe * peut être utilisée dans d'autres cas, car elle se réduit à la sémantique de déplacement C++ 11. En outre, la syntaxe d'initialisation directe a été étendue pour inclure une liste de valeurs d'accolades. –