Que fait un deux-points après le nom d’un constructeur C ++?

Qu’est-ce que l’opérateur deux-points (“:”) fait dans ce constructeur? Est-ce équivalent à MyClass(m_classID = -1, m_userdata = 0); ?

 class MyClass { public: MyClass() : m_classID(-1), m_userdata(0) { } int m_classID; void *m_userdata; }; 

Ceci est une liste d’initialisation et fait partie de l’implémentation du constructeur.

La signature du constructeur est:

 MyClass(); 

Cela signifie que le constructeur peut être appelé sans parameters. Cela en fait un constructeur par défaut , c’est-à-dire un constructeur qui sera appelé par défaut lors de l’écriture de MyClass someObject; .

La partie : m_classID(-1), m_userdata(0) est appelée liste d’initialisation . C’est un moyen d’initialiser certains champs de votre object (tous, si vous le souhaitez) avec les valeurs de votre choix, au lieu de les laisser indéfinies.

Après l’exécution de la liste d’initialisation, le corps du constructeur (qui se trouve être vide dans votre exemple) est exécuté. A l’intérieur, vous pouvez effectuer plus d’affectations, mais une fois que vous l’avez entré, tous les champs ont déjà été initialisés – soit à des valeurs aléatoires, non spécifiées, soit à celles que vous avez choisies dans votre liste d’initialisation. Cela signifie que les affectations que vous effectuez dans le corps du constructeur ne seront pas des initialisations, mais des modifications de valeurs.

C’est une liste d’initialisation.

Au moment où vous entrez dans le corps du constructeur, tous les champs ont déjà été construits; s’ils ont des constructeurs par défaut, ceux-ci étaient déjà appelés. Maintenant, si vous leur atsortingbuez une valeur dans le corps du constructeur, vous appelez l’opérateur d’assignation de copie, ce qui peut signifier libérer et réacquérir des ressources (par exemple, de la mémoire) si l’object en possède.

Donc, dans le cas de types primitifs comme int, il n’y a aucun avantage par rapport à leur atsortingbution dans le corps du constructeur. Dans le cas d’objects ayant un constructeur, il s’agit d’une optimisation des performances car elle évite de passer par deux initialisations d’object au lieu d’une.

Une liste d’initialisation est nécessaire si l’un des champs est une référence, car une référence ne peut jamais être nulle, même dans le court laps de temps entre la construction de l’object et le corps du constructeur. L’erreur suivante soulève l’erreur C2758: ‘MyClass :: member_’: doit être initialisé dans la liste des constructeurs / liste d’initialisation des membres

 class MyClass { public : MyClass(std::ssortingng& arg) { member_ = arg; } std::ssortingng& member_; }; 

La seule manière correcte est:

 class MyClass { public : MyClass(std::ssortingng& arg) : member_(arg) { } std::ssortingng& member_; }; 

Il désigne le début d’une liste d’initialisation, qui sert à initialiser les variables membres de votre object.

En ce qui concerne: MyClass(m_classID = -1, m_userdata = 0);

Cela déclare un constructeur qui peut prendre des arguments (donc je pourrais créer un MyClass utilisant MyClass m = MyClass(3, 4) , ce qui aurait pour résultat m_classID 3 et m_userdata 4). Si je ne transmettais aucun argument au constructeur MyClass , un object équivalent serait créé dans la version avec la liste d’initialisation.

Il signale le début d’une liste d’initialisation.

En outre, il n’est pas équivalent à MyClass (m_classId = -1, m_userData = 0). Cela tente de définir un constructeur avec 2 parameters qui ont des valeurs par défaut. Cependant, les valeurs manquent de types et ne devraient pas être compilées du tout.

C’est une liste d’initialisation . Dans votre exemple, c’est plutôt quelque chose comme ça (quelque chose comme ça – ne veut pas dire que c’est équivalent dans tous les cas):

 class MyClass { public: MyClass(){ m_classID = -1; m_userdata = 0; } int m_classID; void *m_userdata; }; 

Cela s’appelle la liste d’initialisation des membres . Il est utilisé pour appeler les constructeurs de superclasses et donner à vos variables membres une valeur initiale au moment de leur création.

Dans ce cas, il initialise m_classID à -1 et m_userData à NULL.

Ce n’est pas tout à fait équivalent à l’affectation dans le corps du constructeur, car ce dernier crée d’abord les variables membres, puis leur atsortingbue. Avec l’initialisation, la valeur initiale est fournie au moment de la création, donc dans le cas d’objects complexes, cela peut être plus efficace.

Ce n’est pas précisément un opérateur. Cela fait partie de la syntaxe d’un constructeur.

Ce qu’elle dit, c’est qu’il y aura une liste de variables membres et leurs valeurs initiales.

Les membres constants doivent être initialisés de cette manière. Les non-constantes peuvent aussi être initialisées ici, tant que cela peut être fait avec une seule expression. S’il faut plus de code que cela pour initialiser un membre, vous devez mettre le code réel entre les {} pour le faire.

Beaucoup de gens aiment mettre à peu près tout leur code constructeur dans la liste des initilateurs. J’ai un collègue qui écrit régulièrement des classes avec plusieurs écrans d’initialisation, puis met “{}” pour le code constructeur.

C’est le début d’une liste d’initialisation qui définit les variables membres lors de la construction de l’object. Votre exemple “MyClass (m_classID = -1, m_userdata = 0);” n’est pas possible car vous n’avez pas défini le constructeur correct et vous ne pourrez pas accéder aux variables membres dans la liste des parameters de toute façon … vous pourriez avoir quelque chose comme:

 MyClass( int classId = -1, void* userData = 0 ) : m_classID(classId), m_userdata(userData) {} 

La liste d’initialisation est considérée meilleure que:

 MyClass( int classId = -1, void* userData = 0 ) { m_classID = classId; m_userdata = userData; } 

Google pour plus d’informations.

Dans ce cas: Oui, ist est équivalent car seuls les types primitifs sont concernés.

Si les membres sont des classes (structs), vous devriez préférer la liste d’initialisation. En effet, les objects sont construits par défaut, puis assignés.