2010-11-17 20 views
44

Ich habe die folgenden Klassendefinitionen in C++:Wie initialisiert man member-struct in der Initialisierungsliste der C++ Klasse?

struct Foo { 
    int x; 
    char array[24]; 
    short* y; 
}; 

class Bar { 
    Bar(); 

    int x; 
    Foo foo; 
}; 

und möchte die „foo“ Struktur initialisiert werden (mit allen ihren Mitgliedern) auf Null in der Initialisierungsliste der Bar-Klasse. Kann dies auf diese Weise erfolgen:

Bar::Bar() 
    : foo(), 
    x(8) { 
} 

...?

Oder was genau macht die foo (x) in der Initialisierungsliste?

Oder ist die Struktur sogar vom Compiler automatisch auf Null initialisiert?

+3

Beachten Sie, dass Member in der Initialisierungsliste in derselben Reihenfolge aufgelistet werden sollten, in der sie deklariert sind, während Sie zuerst 'x' deklarieren, aber in der Initialisierungsliste den zweiten Platz haben. –

Antwort

49

Zuerst sollten Sie (müssen!) Diese c++ faq in Bezug auf POD und Aggregate lesen. In Ihrem Fall ist Foo in der Tat eine POD-Klasse und foo() ist ein Wert Initialisierung:

Um Wert initialisieren ein Objekt vom Typ T bedeutet:

  • wenn T eine Klasse Typ (Klausel 9) mit einem benutzerdeklarierten Konstruktor (12.1), dann wird der Standardkonstruktor
    für T aufgerufen (und die Initialisierung ist schlecht ausgebildet, wenn T keinen zugänglichen Standardkonstruktor hat);
  • Wenn T ein nicht gewerkschaftlich organisierter Klassentyp ohne vom Benutzer deklarierten Konstruktor ist, dann wird jeder nicht statische Datenmember und die Basisklassenkomponente von T initialisiert.
  • Wenn T ein Array-Typ ist, wird jedes Element initialisiert.
  • sonst wird das Objekt-Null initialisiert

Also ja, wird foo Null initialisiert werden. Beachten Sie, dass, wenn Sie diese Initialisierung von Bar Konstruktor entfernt, foo nur wäre default-initialisiert:

Wenn kein Initialisierer für ein Objekt angegeben, und das Objekt von (möglicherweise cv-qualifiziert) nicht -POD-Klassentyp (oder Array davon), das Objekt muss default-initialisiert sein; Wenn das Objekt des Typs const-qualified ist, muss der zugrunde liegende Klassentyp über einen benutzerdefinierten Konstruktor verfügen, der von deklariert wurde. Andernfalls, wenn kein Initialisierer für ein nicht statisches Objekt angegeben wird, das Objekt und seine Unterobjekte, sofern vorhanden, haben einen unbestimmten Anfangswert ;

+2

Was, wenn foo als a definiert wurde bestes Mitglied? – RezaPlusPlus

8

In Standard C++ müssen Sie einen Ctor für Foo machen.

struct Foo { 

    Foo(int const a, std::initializer_list<char> const b, short* c) 
    : x(a), y(c) { 
    assert(b.size() >= 24, "err"); 
    std::copy(b.begin(), b.begin() + 24, array); 
    } 

    ~Foo() { delete y; } 

    int x; 
    char array[24]; 
    short* y; 
}; 

class Bar { 

    Bar() : x(5), foo(5, {'a', 'b', ..., 'y', 'z'}, 
    new short(5)) { } 

    private: 

    int x; 
    Foo foo; 
}; 

In C++ 0x Sie einheitliche Initialisierungsliste verwenden können, aber Sie müssen noch dtor für Foo:

class Bar { 

    Bar() : x(5), foo{5, new char[24]{'a', 'b', ..., 'y', 'z'}, 
    new short(5)} { } 
    ~Bar() { delete[] foo.array; delete foo.y;} 
    } 
    private: 

    int x; 
    Foo foo; 
}; 

Standard foo initialisiert werden (wie Bar() : foo(), x(8) { }) Sie Foo eine Standard Ctor geben müssen .

+2

Dies ist ein wenig unklar, wo Sie C++ 03 vs C++ 0x verwenden. IIRC 'initializer_list' ist Teil von C++ 0x. Außerdem haben Sie in Ihrem zweiten Codeblock zwei Speicherlecks erstellt. –

+0

@Fabio: Danke, dass du das herausgibst, editiert – erjot

+0

jetzt hast du eine doppelte Löschung ('foo.y') und ein Speicherleck (vom' neuen Zeichen [24] ', außerdem bin ich nicht sicher (aber ich könnte falsch sein hier), dass dies die Art ist, 'initializer_list' zu verwenden. –

Verwandte Themen