Frage Was macht ein Doppelpunkt, der einem C ++ - Konstruktornamen folgt? [Duplikat]


Diese Frage hat hier bereits eine Antwort:

Was macht der Doppelpunktoperator (":") in diesem Konstruktor? Ist es gleichbedeutend mit MyClass(m_classID = -1, m_userdata = 0);?

class MyClass {
public:

    MyClass() : m_classID(-1), m_userdata(0) { 
    }

    int m_classID;
    void *m_userdata;
};

76
2017-08-13 15:22


Ursprung


Antworten:


Das ist ein Initialisierungsliste, und ist Teil der Implementierung des Konstruktors.

Die Unterschrift des Konstruktors lautet:

MyClass();

Dies bedeutet, dass der Konstruktor ohne Parameter aufgerufen werden kann. Dies macht es zu einem Standardkonstruktorh. einer, der beim Schreiben standardmäßig aufgerufen wird MyClass someObject;.

Der Teil : m_classID(-1), m_userdata(0) wird genannt Initialisierungsliste. Es ist eine Möglichkeit, einige Felder Ihres Objekts (alle, wenn Sie möchten) mit Werten Ihrer Wahl zu initialisieren, anstatt sie als undefiniert zu belassen.

Nach dem Ausführen der Initialisierungsliste wird der Konstruktorhauptteil (der in Ihrem Beispiel leer ist) ausgeführt. Darin könnten Sie mehr Zuweisungen machen, aber sobald Sie es eingegeben haben, wurden alle Felder bereits initialisiert - entweder zu zufälligen, nicht spezifizierten Werten oder zu denen, die Sie in Ihrer Initialisierungsliste ausgewählt haben. Das bedeutet, dass die Zuweisungen, die Sie im Konstruktorhauptteil vornehmen, keine Initialisierungen, sondern Änderungen von Werten sind.


82
2017-08-13 15:26



Es ist eine Initialisierungsliste.

Zu dem Zeitpunkt, an dem Sie in den Hauptteil des Konstruktors gelangen, sind alle Felder bereits konstruiert. Wenn sie Standardkonstruktoren haben, wurden diese bereits aufgerufen. Wenn Sie ihnen nun einen Wert im Rumpf des Konstruktors zuweisen, rufen Sie den Kopierzuweisungsoperator auf, was bedeuten kann, Ressourcen (z. B. Speicher) freizugeben und wiederzuerlangen, wenn das Objekt eines besitzt.

Im Fall von primitiven Typen wie int gibt es also keinen Vorteil, wenn man sie im Rumpf des Konstruktors zuordnet. Bei Objekten mit einem Konstruktor handelt es sich um eine Leistungsoptimierung, da zwei Objektinitialisierungen anstelle von einem vermieden werden.

Eine Initialisierungsliste ist erforderlich, wenn eines der Felder eine Referenz ist, da eine Referenz niemals null sein kann, auch nicht in der kurzen Zeit zwischen der Objektkonstruktion und dem Rumpf des Konstruktors. Das folgende löst Fehler C2758: "MyClass :: member_": muss in Konstruktor Base / Member Initializer-Liste initialisiert werden

class MyClass {
public :
    MyClass(std::string& arg) {
        member_ = arg;
    }
    std::string& member_;
};

Der einzig richtige Weg ist:

class MyClass {
public :
    MyClass(std::string& arg) 
        : member_(arg) 
    {
    }
    std::string& member_;
};

40
2017-08-13 15:37



Es kennzeichnet den Anfang einer Initialisierungsliste, die zum Initialisieren von Elementvariablen Ihres Objekts dient.

Zu: MyClass(m_classID = -1, m_userdata = 0);

Das deklariert einen Konstruktor, der Argumente übernehmen kann (also könnte ich ein MyClass verwenden MyClass m = MyClass(3, 4), was dazu führen würde m_classID 3 und sein m_userdata sein 4). Wenn ich keine Argumente an die MyClass Konstruktor würde ein äquivalentes Objekt zu der Version mit der Initialisiererliste erstellt werden.


2
2017-08-13 15:25



Es signalisiert den Beginn einer Initialisierungsliste.

Außerdem entspricht es nicht MyClass (m_classId = -1, m_userData = 0). Dies versucht einen Konstruktor mit 2 Parametern zu definieren, die Standardwerte haben. Die Werte fehlen jedoch und sollten nicht kompiliert werden.


2
2017-08-13 15:27



Es ist ein Initialisierungsliste. In Ihrem Beispiel ist es eher so (etwas ähnliches - bedeutet nicht, dass es in allen Fällen gleichwertig ist):


class MyClass {

public:

    MyClass(){
         m_classID = -1;
         m_userdata = 0;
    }

    int m_classID;
    void *m_userdata;

};

1
2017-08-13 15:26



Das nennt man das Mitgliedsinitialisierungsliste. Es wird verwendet, um die Konstruktoren der Superklasse aufzurufen, und gibt Ihren Membervariablen zum Zeitpunkt ihrer Erstellung einen Anfangswert.

In diesem Fall wird initialisiert m_classID bis -1 und m_userData zu NULL.

Es ist nicht ganz gleichbedeutend mit der Zuweisung im Rumpf des Konstruktors, da dieser zuerst die Elementvariablen erstellt und ihnen dann zuordnet. Bei der Initialisierung wird der Anfangswert zum Zeitpunkt der Erstellung bereitgestellt, sodass er bei komplexen Objekten effizienter sein kann.


1
2017-08-13 15:27



Es ist nicht gerade ein Operator. Es ist ein Teil der Syntax für einen Konstruktor.

Was es sagt, ist, dass es eine Liste von Mitgliedsvariablen und deren Anfangswerte sein wird.

Konstante Mitglieder müssen auf diese Weise initialisiert werden. Nicht-Konstanten können auch hier initialisiert werden, solange dies mit einem einzelnen Ausdruck möglich ist. Wenn mehr Code benötigt wird, um einen Member zu initialisieren, müssen Sie den tatsächlichen Code zwischen die {} setzen.

Viele Leute stellen ihren Konstruktorcode so gut wie in die Initialisierungsliste. Ich habe einen Kollegen, der regelmäßig Klassen mit mehreren Bildschirmen von Initialisierern schreibt und dann "{}" für den Konstruktorcode eingibt.


1
2017-08-13 15:28



Es ist der Anfang einer Initialisierungsliste, die Elementvariablen während der Konstruktion des Objekts festlegt. Ihr Beispiel "MyClass (m_classID = -1, m_userdata = 0);" ist nicht möglich, da Sie den richtigen Konstruktor nicht definiert haben und Sie nicht auf die Elementvariablen in der Parameterliste zugreifen könnten ... Sie könnten etwas haben wie:

MyClass( int classId = -1, void* userData = 0 ) : m_classID(classId), m_userdata(userData) {}

Die Initialisiererliste gilt als besser als:

MyClass( int classId = -1, void* userData = 0 ) {
    m_classID = classId;
    m_userdata = userData;
}

Google für weitere Informationen.


1
2017-08-13 15:29