Que signifient les phrases suivantes en C++: initialisation par zéro, par défaut et valeur?

que signifient les phrases suivantes en C++:

  • zéro-initialisation,

  • défaut d'initialisation, et

  • la valeur d'initialisation

que devrait savoir un développeur C++ à leur sujet?

167
demandé sur Destructor 2009-10-23 17:14:45

2 réponses

une chose à réaliser est que "value-initialization" est nouveau avec la norme c++ 2003 - il n'existe pas dans la norme originale de 1998 (je pense que ce pourrait être la seule différence qui est plus qu'une clarification). Voir Kirill V. Lyadvinsky's answer pour les définitions tirées directement de la norme.

Voir cette réponse précédente sur le comportement de operator new pour plus de détails sur le comportement différent de ces type d'initialisation et quand ils font effet (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 le nouvel opérateur sera initialisée, et parfois elle ne dépendra pas de si le type que vous mettez en place est un POD, ou si c'est une classe qui contient des membres POD et utilise un constructeur par défaut généré par le compilateur.

  • En C++1998 il y a 2 types d'initialisation: le zéro et la valeur par défaut
  • dans C++2003 un 3ème type d'initialisation, l'initialisation de la valeur a été ajoutée.

pour le moins, c'est assez complexe et quand les différentes méthodes font leur entrée, elles sont subtiles.

une chose dont il faut être conscient est-ce que MSVC suit les règles C++98, même dans VS 2008 (VC 9 ou cl.exe de la version 15.x).

l'extrait suivant montre que MSVC et Mars numérique suivent les règles C++98, tandis que GCC 3.4.5 et Comeau suivent les règles C++03:

#include <stdio.h>
#include <string.h>
#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)];
    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
    printf( "m  is %d\n", pB->m);
    return 0;
}
57
répondu Michael Burr 2017-05-23 12:10:44

C++03 Standard 8.5/ 5:

à zéro-initialiser un objet du type T signifie:

- Si T est un type scalaire (3.9), l'objet est réglé à la valeur 0 (zéro) convertie en T;

- Si T est un type de classe non syndicale, chaque membre de données non statiques et chaque sous-objet de classe de base est zéro-initialisé;

- Si T est un type d'union, le le premier membre de données nommé de l'objet est zéro-initialisé;

- Si T est un type de tableau, chaque élément est initialisé à zéro;

- Si T est un type de référence, aucune initialisation n'est effectuée.

à par défaut-initialiser un objet de type T signifie:

- 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 accessible le constructeur par défaut);

- Si T est un type de tableau, chaque élément est initialisé par défaut;

- sinon, l'objet est initialisé à zéro.

à valeur-initialiser un objet de type T signifie:

- Si T est un type de classe (clause 9) avec un constructeur déclaré par l'utilisateur (12.1), alors le constructeur par défaut pour T est appelé (et l'initialisation est mal formée si T n'a pas de constructeur par défaut accessible);

- Si T est un type de classe non-union sans un constructeur déclaré par l'utilisateur, alors chaque membre de données non-statiques et composante de classe de base de T est valeur-initialisée;

- Si T est un type de tableau, alors chaque élément est valeur-initialisée;

-sinon, l'objet est zéro-initialisé

un programme qui appelle à par défaut-initialisation ou valeur-l'initialisation d'une entité de type de référence est mal formée. Si T est un type qualifié cv, la version cv-unqualified de T est utilisée pour ces définitions de Zero-initialization, default-initialization, et value-initialization.

81
répondu Kirill V. Lyadvinsky 2009-10-23 13:20:55