it-swarm.com.de

C++ - Initialisieren von Variablen im Header vs mit Konstruktor

Gibt es Gründe für die folgenden Punkte, oder sind sie ungefähr gleichwertig?

class Something
{
    int m_a = 0;
};

vs

class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };
28
Evan Ward

Die beiden Code-Snippets, die Sie gepostet haben, sind nicht ganz gleich .

class Something
{
    int m_a = 0;
};

Hier legen Sie den Wert fest, mit dem zur Kompilierzeit initialisiert werden soll, d. H. 0.

class Something
{
    int m_a;
    Something(int p_a);
};

Something::Something(int p_a):m_a(p_a){ ... };

Und hier machen Sie es zur run time (oder möglicherweise zur Laufzeit), wobei der Wert p_a nicht bekannt ist, bis der Konstruktor aufgerufen wird.

Der folgende Code kommt Ihrem ersten Beispiel näher:

class Something
{
    int m_a;
    Something();
};

Something::Something() : m_a(0) { /* ... */ };

Hierbei ist zu beachten, dass der Wert im ersten Fall direkt in der Klassendefinition erscheint. Dies kann zu einer unnötigen Abhängigkeit führen. Was passiert, wenn Sie Ihren 0 später in 1ändern müssen? Wenn der Wert direkt in der Klassendefinition (und normalerweise in einer Headerdatei) verfügbar gemacht wird, kann dies in Situationen, in denen die andere Form der Initialisierung dies vermeiden würde, zu einer erneuten Kompilierung von viel Code führen, da der Something::Something() : m_a(0)-Teil in einer Quelle ordentlich gekapselt wird Datei und nicht in einer Header-Datei erscheinen:

// Something.h - stable header file, never changed
class Something
{
    int m_a;
    Something();
};

// Something.cpp - can change easily
Something::Something() : m_a(0) { /* ... */ };

Natürlich können die Vorteile der In-Class-Initialisierung diesen Nachteil bei weitem überwiegen. Es hängt davon ab, ob. Sie müssen es nur im Hinterkopf behalten.

36
Christian Hackl

Das erste Formular ist bequemer, wenn Sie mehr als einen Konstruktor haben (und möchten, dass alle das Element auf dieselbe Weise initialisieren) oder wenn Sie keinen Konstruktor schreiben müssen.

Die zweite ist erforderlich, wenn der Initialisierer von Konstruktorargumenten abhängt oder sonst für die Initialisierung in der Klasse zu kompliziert ist. und es könnte besser sein, wenn der Konstruktor kompliziert ist, um die gesamte Initialisierung an einem Ort zu behalten. (Und es ist auch erforderlich, wenn Sie Pre-C++ 11-Compiler unterstützen müssen.)

12
Mike Seymour

Das erste Formular ist neu in C++ 11 und wird daher an dieser Stelle nicht besonders gut unterstützt, insbesondere wenn Sie verschiedene ältere Compiler unterstützen müssen.

Ansonsten sollten sie ungefähr gleich sein, wenn ein C++ 11-Compiler verfügbar ist.

5
Mark B

Ausarbeitung der Antwort von Christian Hackl.

Das erste Formular ermöglicht es, m_a zu initialisieren und gleichzeitig ein Standardc'tor zu haben. Oder Sie können in Ihrem Code sogar explizit sein und einen Konstruktor mit dem Schlüsselwort default definieren:

class Something
{       
    int m_a = 0;

    // explicitly tell the compiler to generate a default c'tor
    Something() = default;
};

Mit dem zweiten Formular würde ein automatisch generierter Standardc'tor m_a nicht initialisiert. Wenn Sie also einen hartcodierten Wert verwenden möchten, müssen Sie einen eigenen Standardc'tor schreiben:

class Something
{
    int m_a;

    // implement your own default c'tor
    Something() : m_a(0) {}
};
3
Alexey Polonsky
class Something
{
    int m_a = 0;
};

ist äquivalent zu 

class Something
{
    int m_a(0);
};

Also tun 

class Something
{
    int m_a;// (0) is moved to the constructor
public:
    Something(): m_a(0){}
};

ergibt eine einheitliche Syntax für die Initialisierung, die eine Runtime-Eingabe erfordert oder nicht erfordert.

Ich persönlich mag das erste Formular nicht, weil es wie eine "Deklaration, dann eine Zuweisung" aussieht.

0
user3528438