188 votes

Comment faire de la classe C++ membres de l'initialisation si je ne le fais pas de façon explicite?

Supposons que j'ai une classe avec salle de cadres ptr, name, pname, rname, crname et age. Qu'advient-il si je n'ai pas l'initialiser moi-même? Voici un exemple:

class Example {
    private:
        int *ptr;
        string name;
        string *pname;
        string &rname;
        const string &crname;
        int age;

    public:
        Example() {}
};

Et puis je fais:

int main() {
    Example ex;
}

Comment les membres initialisé en ex? Ce qui se passe avec des pointeurs? N' string et int obtenir 0-initialisée avec les constructeurs par défaut string() et int()? Quel est le membre de référence? Aussi ce sujet const références?

Que dois-je savoir?

Quelqu'un sait-il un tutoriel qui couvre ces cas? Peut-être que dans quelques livres? J'ai accès à la bibliothèque de l'université de beaucoup de C++ livres.

Je voudrais savoir si je peux écrire mieux (sans bug) des programmes. Toutes les réactions de l'aide!

246voto

Tyler McHenry Points 35551

En lieu et place de l'initialisation explicite, l'initialisation des membres dans les classes fonctionne de la même manière à l'initialisation des variables locales des fonctions.

Pour les objets, leur constructeur par défaut est appelé. Par exemple, pour std::string, le constructeur par défaut définit une chaîne vide. Si la classe de l'objet ne possède pas de constructeur par défaut, ce sera une erreur de compilation si vous n'avez pas explicitement l'initialiser.

Pour les types primitifs (pointeurs, ints, etc), ils sont pas initialisés-ils contenir n'importe quoi arbitraire indésirable qui est arrivé à être à l'emplacement de mémoire précédemment.

Pour les références (par exemple, std::string&), il est illégal de ne pas les initialiser, et votre compilateur va se plaindre, et de refuser de compiler ce code. Les références doivent toujours être initialisé.

Donc, dans votre cas précis, si elles ne sont pas explicitement initialisée:

    int *ptr;  // Contains junk
    string name;  // Empty string
    string *pname;  // Contains junk
    string &rname;  // Compile error
    const string &crname;  // Compile error
    int age;  // Contains junk

30voto

Daniel Trebbien Points 18089

Tout d'abord, laissez-moi vous expliquer ce qu'est un mem-initialiseur-liste est. Un mem-initialiseur-liste est une liste séparée par des virgules des mem-initialiseurs, où chaque mem-initialiseur est le nom d'un membre suivi par (, suivi par une expression de la liste, suivi par un ). L' expression-de la liste est la façon dont le membre est construit. Par exemple, dans

static const char s_str[] = "bodacydo";
class Example
{
private:
    int *ptr;
    string name;
    string *pname;
    string &rname;
    const string &crname;
    int age;

public:
    Example()
        : name(s_str, s_str + 8), rname(name), crname(name), age(-4)
    {
    }
};

les mem-initialiseur-liste de l'utilisateur fourni, non-arguments constructeur name(s_str, s_str + 8), rname(name), crname(name), age(-4). Cette mem-initialiseur-liste des moyens que l' name membre est initialisé par l' std::string constructeur qui prend deux itérateurs, l' rname membre est initialisé avec une référence à l' name, crname membre est initialisé avec un const référence- name, et l' age membre est initialisé avec la valeur -4.

Chaque constructeur a sa propre mem-initialiseur-liste, et les membres ne peut être initialisé dans un certain ordre (en gros, l'ordre dans lequel les membres sont déclarées dans la classe). Ainsi, les membres de l' Example ne peut être initialisé lors de la commande: ptr, name, pname, rname, crname, et age.

Lorsque vous ne spécifiez pas un mem-initialiseur d'un membre, la norme C++, dit:

Si l'entité est un non membre de données ... de type de classe ..., l'entité est par défaut-initialisé (8.5). ... Dans le cas contraire, l'entité n'est pas initialisé.

Ici, parce qu' name est un non membre de données de type de classe, il est par défaut-initialisé si pas d'initialiseur pour name a été spécifié dans la mem-initialiseur-liste. Tous les autres membres de l' Example n'ont pas de type de classe, de sorte qu'ils ne sont pas initialisés.

Lorsque la norme dit qu'ils ne sont pas initialisés, cela signifie qu'elles peuvent avoir aucune valeur. Ainsi, parce que le code ci-dessus n'a pas initialiser pname, il pourrait être n'importe quoi.

Notez que vous devez toujours suivre d'autres règles, telles que la règle de références doivent toujours être initialisé. C'est une erreur de compilateur de ne pas initialiser les références.

10voto

Paul Dixon Points 122033

Si vous avez l'exemple de la classe est instanciée sur la pile, le contenu de initialisée scalaire membres est aléatoire et non défini.

Pour une instance globale, non initialisée scalaire membres seront remis à zéro.

Pour les membres qui sont eux-mêmes des instances de classes, de leurs constructeurs par défaut sera appelé, de sorte que votre chaîne de l'objet de l'initialisation.

  • int *ptr; //pointeur non initialisé (ou remis à zéro si global)
  • string name; //constructeur appelé, initialisé avec une chaîne vide
  • string *pname; //pointeur non initialisé (ou remis à zéro si global)
  • string &rname; //erreur de compilation si vous ne parvenez pas à initialiser cette
  • const string &crname; //erreur de compilation si vous ne parvenez pas à initialiser cette
  • int age; //valeur scalaire, non initialisée et aléatoire (ou remis à zéro si global)

5voto

Wizard Points 524

Non initialisée les membres non statiques contiennent des données aléatoires. En fait, ils ont juste la valeur de l'emplacement de mémoire ils sont affectés.

Bien sûr, pour les paramètres de l'objet (comme string) le constructeur de l'objet pourrait faire une initialisation par défaut.

Dans votre exemple:

int *ptr; // will point to a random memory location
string name; // empty string (due to string's default costructor)
string *pname; // will point to a random memory location
string &rname; // it would't compile
const string &crname; // it would't compile
int age; // random value

2voto

janm Points 9310

Les membres avec un constructeur par défaut constructeur appelé pour l'initialisation.

Vous ne pouvez pas dépendre du contenu des autres types.

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