Que signifient les phrases suivantes en C ++:
zéro-initialisation,
initialisation par défaut, et
initialisation de la valeur
Que doit savoir un développeur C ++ à leur sujet?
Que signifient les phrases suivantes en C ++:
zéro-initialisation,
initialisation par défaut, et
initialisation de la valeur
Que doit savoir un développeur C ++ à leur sujet?
Réponses:
Une chose à réaliser est que «l'initialisation de la valeur» est nouvelle avec la norme C ++ 2003 - elle n'existe pas dans la norme originale de 1998 (je pense que c'est peut-être la seule différence qui est plus qu'une clarification). Voir la réponse de Kirill V. Lyadvinsky pour les définitions directement issues de la norme.
Voir cette réponse précédente sur le comportement de operator new
pour plus de détails sur les différents comportements de ces types d'initialisation et quand ils se déclenchent (et quand ils diffèrent de C ++ 98 à C ++ 03):
Le point principal de la réponse est:
Parfois, la mémoire retournée par l'opérateur new sera initialisée, et parfois cela ne dépendra pas si le type que vous créez est un POD, ou s'il s'agit d'une classe qui contient des membres POD et utilise un constructeur par défaut généré par le compilateur .
- Dans C ++ 1998, il existe 2 types d'initialisation: zéro et par défaut
- Dans C ++ 2003, un troisième type d'initialisation, l'initialisation de la valeur a été ajoutée.
Pour dire le moins, c'est plutôt complexe et quand les différentes méthodes entrent en jeu sont subtiles.
Il faut certainement savoir que MSVC suit les règles du C ++ 98, même dans VS 2008 (VC 9 ou cl.exe version 15.x).
L'extrait suivant montre que MSVC et Digital Mars suivent les règles C ++ 98, tandis que GCC 3.4.5 et Comeau suivent les règles C ++ 03:
#include <cstdio>
#include <cstring>
#include <new>
struct A { int m; }; // POD
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
struct C { C() : m() {}; ~C(); int m; }; // non-POD, default-initialising m
int main()
{
char buf[sizeof(B)];
std::memset( buf, 0x5a, sizeof( buf));
// use placement new on the memset'ed buffer to make sure
// if we see a zero result it's due to an explicit
// value initialization
B* pB = new(buf) B(); //C++98 rules - pB->m is uninitialized
//C++03 rules - pB->m is set to 0
std::printf( "m is %d\n", pB->m);
return 0;
}
int
, mais m()
sur la troisième ligne, la valeur initialise m. Important si vous passez int m;
à B m;
. :)
A
et C
ne sont pas utilisés dans cet exemple (ils sont reportés de l'autre réponse liée). Même si C ++ 98 et C ++ 03 utilisent une terminologie différente pour décrire comment A
et C
sont construits, le résultat est le même dans les deux normes. Il en struct B
résulte seulement un comportement différent.
struct C { C() : m() {}; ~C(); B m; };
, alors vous aurez m.m
la valeur 0. Mais s'il était initialisé par défaut m
comme vous le dites C ++ 03, alors il m.m
ne serait pas initialisé comme dans C ++ 98.
Norme C ++ 03 8.5 / 5:
Initialiser à zéro un objet de type T signifie:
- si T est un type scalaire (3.9), l'objet est mis à la valeur 0 (zéro) convertie en T;
- si T est un type de classe non-union, chaque membre de données non statique et chaque sous-objet de classe de base est initialisé à zéro;
- si T est un type union, le premier membre de données nommé de l'objet est initialisé à zéro;
- si T est un type tableau, chaque élément est initialisé à zéro;
- si T est un type référence, aucune initialisation n'est effectuée.Pour default-initialiser un objet de moyens de type T:
- si T est un type de classe non-POD (clause 9), le constructeur par défaut pour T est appelé (et l'initialisation est mal formé si T n'a pas de constructeur par défaut accessible);
- si T est un type tableau, chaque élément est initialisé par défaut;
- sinon, l'objet est initialisé à zéro.Pour la valeur initialiser un objet de moyens de type T:
- si T est un type de classe (clause 9) avec un constructeur déclarée par l' utilisateur (12.1), le constructeur par défaut pour T est appelé (et l'initialisation est mal formé si T n'a pas de constructeur par défaut accessible);
- si T est un type de classe non-union sans constructeur déclaré par l'utilisateur, alors chaque membre de données non statique et composant de classe de base de T est initialisé par la valeur;
- si T est un type tableau, alors chaque élément est initialisé par une valeur;
- sinon, l'objet est initialisé à zéroUn programme qui appelle une initialisation par défaut ou une initialisation de valeur d'une entité de type référence est mal formé. Si T est un type qualifié cv, la version non qualifiée cv de T est utilisée pour ces définitions d'initialisation zéro, d'initialisation par défaut et d'initialisation de valeur.