96 votes

Initialisation des champs dans le constructeur - liste d'initialisation vs corps du constructeur

Je travaille en c++ depuis un certain temps maintenant, mais je ne suis pas sûr de la différence entre

public : Thing(int _foo, int _bar): member1(_foo), member2(_bar){}

y

public : Thing(int _foo, int _bar){
    member1 = _foo;
    member2 = _bar;
}

J'ai l'impression qu'elles font la même chose, mais y a-t-il une différence pratique entre ces 2 syntaxes. L'une d'entre elles est-elle plus sûre que l'autre, et gèrent-elles différemment les paramètres par défaut ?

Je ne suis pas totalement habitué au premier exemple, donc si j'ai fait une erreur à ce sujet, je m'en excuse.

108voto

Luchian Grigore Points 136646

Ils ne sont pas les mêmes si member1 y member2 sont non POD (c'est-à-dire non P lain O ld D ata ) :

public : Thing(int _foo, int _bar){
    member1 = _foo;
    member2 = _bar;
}

est équivalent à

public : Thing(int _foo, int _bar) : member1(), member2(){
    member1 = _foo;
    member2 = _bar;
}

parce qu'ils seront initialisés avant que le corps du constructeur ne commence à s'exécuter, donc en fait, le double du travail est fait. Cela signifie également que, si le type de ces membres n'a pas de constructeur par défaut, alors votre code sera no compiler.

30voto

Péter Török Points 72981

La première est la meilleure pratique recommandée, car elle est plus idiomatique et évite de réinitialiser les champs pour les types qui ont un constructeur par défaut (c'est-à-dire les types non primitifs).

Lorsque vous initialisez un membre uniquement dans le corps du constructeur, le compilateur génère une déclaration d'initialisation de membre par défaut pour vous s'il le peut, de sorte que vous finissez par l'initialiser doublement. Cela peut ne pas être un gros problème dans certains cas, mais peut représenter un sérieux surcoût de performance si la construction de l'objet est coûteuse.

Mise à jour

Cependant, les types définis par l'utilisateur sans constructeur par défaut (explicitement défini ou généré) ne peuvent pas être initialisés de cette façon, ce qui entraîne une erreur de compilation. Il en va de même pour les champs const et de référence - ceux-ci ne peuvent être initialisés que de manière explicite dans la liste des initialisateurs de membres.

18voto

PaperBirdMaster Points 2262

La seule chose à ajouter à Peter Török La réponse est que la liste d'initialisation est le seul moyen d'initialiser les membres constants des objets, c'est-à-dire :

class foo
{
public:

    foo(int value)
        : myConstValue(value)
    {};

    foo()
    {
        myConstValue = 0; // <=== Error! myConstValue is const (RValue), you can't assign!
    };

private:
    const int myConstValue;
}

6voto

Sanish Points 1287

Dans votre exemple de code, le premier est dans l'initialisation du constructeur et le second est une affectation à l'intérieur du corps du constructeur.

La liste d'initialisation du constructeur est la meilleure façon de procéder à l'initialisation de tous les membres, car elle améliore les performances.

class A
{
string name;
public:
A(string myname):name(myname) {}
}

Dans le cas ci-dessus, le compilateur ne créera pas d'objet temporaire pour faire l'initialisation. Cependant, dans le cas suivant :

A::A()
{
    name = myname;
}

Un objet temporaire séparé est créé, et cet objet temporaire est transmis à string L'opérateur d'affectation de l'UE permet d'assigner à name . Ensuite, l'objet temporaire est détruit, ce qui n'est pas très efficace.

Note : Il est obligatoire qu'une référence ou un membre const soit initialisé dans la liste d'initialisation d'un constructeur. Ils ne peuvent pas être "assignés" dans le corps du constructeur.

2voto

En dehors des autres réponses, je voudrais mentionner que l'initialisation du constructeur ne sert qu'à initialiser les variables membres.

class Demo
{
    int a;
    int b;
public:
    Demo(int a,int b):a(a),b(b)
    {

    }

};

si nous initialisons a et b dans le constructeur, ce serait une auto-assignation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X