Eine Konstruktorinitialisierungsliste beginnt mit einem Doppelpunkt, gefolgt von einer durch Kommas getrennten Liste von Datenmembern, wobei auf jeden Datenmember ein Initialisierer in Klammern folgt. Zum Beispiel:

class CExample {
public:
    int a;
    float b;
    //构造函数初始化列表
    CExample(): a(0),b(8.8)
    {}
    //构造函数内部赋值
    CExample()
    {
        a=0;
        b=8.8;
    }
};

Im obigen Beispiel sind die Ergebnisse der beiden Konstruktoren gleich. Der obige Konstruktor (derjenige, der die Initialisierungsliste verwendet) initialisiert die Member der Klasse explizit; während der Konstruktor, der die Initialisierungsliste nicht verwendet, den Membern der Klasse Werte zuweist, ohne explizite Initialisierung.

Initialisierung und Zuweisung machen bei Membern von eingebauten Typen kaum einen Unterschied, daher funktioniert jeder der obigen Konstruktoren. Für Membervariablen von nicht eingebauten Typen wird empfohlen, die Konstruktorinitialisierungsliste der Klasse zu verwenden, um doppeltes Konstruieren zu vermeiden. Manchmal ist jedoch ein Konstruktor mit einer Initialisierungsliste erforderlich:

  • 1. Der Membertyp isteine Klasse ohne Standardkonstruktor. Wenn kein expliziter Initialisierer angegeben wird, verwendet der Compiler implizit den Standardkonstruktor des Membertyps. Wenn die Klasse keinen Standardkonstruktor hat, schlägt der Versuch des Compilers fehl, den Standardkonstruktor zu verwenden.const-Member
  • 2.const-MemberoderReferenztyp-Member. Da const-Objekte oder Referenztypen nur initialisiert und ihnen keine Werte zugewiesen werden können.

Was bedeutet es, Datenmember zu initialisieren, im Gegensatz dazu, ihnen Werte zuzuweisen? Worin liegt der Unterschied?

Zuerst werden Datenmember nach Typ klassifiziert und jeder Fall erläutert:

  • 1.Eingebaute Datentypen, zusammengesetzte Typen (Zeiger, Referenzen)- Es in der Memberinitialisierungsliste oder im Konstruktorkörper zu tun, ist in Leistung und Ergebnis gleich.
  • 2.Benutzerdefinierte Typen (Klassentypen)- Die Ergebnisse sind dieselben, aber es gibt einen großen Unterschied in der Leistung. Da Objekte von Datenmembern vom Klassentyp bereits vor dem Eintritt in den Funktionsrumpf konstruiert werden, das heißt, die Konstruktionsarbeit erfolgt in der Member-Initialisierungsliste durch Aufruf des Konstruktors. Nach dem Eintritt in den Funktionsrumpf werden den bereits konstruierten Klassenobjekten Werte zugewiesen, was den Aufruf eines Kopierzuweisungsoperators erfordert (falls nicht bereitgestellt, wird das vom Compiler bereitgestellte standardmäßige elementweise Zuweisungsverhalten verwendet).

Notizen:

Reihenfolge der Member-Initialisierung in der Initialisierungsliste:

C++ initialisiert Klassenmember in der Reihenfolge, in der sie deklariert sind, nicht in der Reihenfolge, in der sie in der Initialisierungsliste erscheinen.

class CMyClass {
    CMyClass(int x, int y);
    int m_x;
    int m_y;
};

CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
{
};

Sie könnten denken, dass der obige Code zuerst m_y=I ausführt, dann m_x=m_y, und schließlich haben sie denselben Wert. Aber der Compiler initialisiert zuerst m_x, dann m_y, weil sie in dieser Reihenfolge deklariert sind. Infolgedessen hat m_x einen unvorhersehbaren Wert. Es gibt zwei Möglichkeiten, dies zu vermeiden: Eine besteht darin, Member immer in der Reihenfolge zu deklarieren, in der sie initialisiert werden sollen; die zweite besteht darin, wenn Sie sich entscheiden, eine Initialisierungsliste zu verwenden, die Member immer in der Reihenfolge aufzulisten, in der sie deklariert sind. Dies hilft, Verwirrung zu vermeiden.

Originaladresse: http://www.cnblogs.com/BlueTzar/articles/1223169.html