2013-08-01 10 views
7

Als Selbst Übung, ich habe diesen einfachen Code geschrieben:Muss ein Referenztyp in der Initialisierungsliste des Konstruktors initialisiert werden?

#include <iostream> 

int gIndex = 3; 

template <class T> class Array 
{ 
public: 
    explicit Array(int size); 
    T& operator[](int i) { return m_data[i]; } 
    T operator[](int i) const { return m_data[i]; } 
    T getAnchorPoint() const { return m_data[m_anchor]; } 
private: 
    T* m_data; 
    int m_size; 
    int& m_anchor; 
}; 

template <class T> Array<T>::Array(int size) : m_size(size), m_data(new T[size]) 
{ 
    memset(m_data, 0, size*sizeof(T)); 
    m_anchor = gIndex; 
} 

int main() 
{ 
    Array<double> a(10); 
    return 0; 
} 

ich einen Kompilierungsfehler bekam, die sagt:

error C2758: 'Array<T>::m_anchor' : must be initialized in constructor base/member initializer list

Es ist nie passiert ist, was mich dies zu fragen bringt Frage:

Muss ein Klassenmitglied-Referenztyp in der Errichterinitialisierungsliste initialisiert werden?

Wenn ja, warum? Ist das irgendwie damit zu tun, dass ein Referenztyp niemals neu zugeordnet werden kann?

Gibt es mehr Typen, die in der Initialisierungsliste des Konstruktors initialisiert werden müssen?

Antwort

12

Muss ein Klassenmitglied-Referenztyp in der Errichterinitialisierungsliste initialisiert werden?

Ja.

Wenn ja, warum? Ist das irgendwie damit zu tun, dass der Referenztyp nie neu vergeben werden kann?

Das ist ein Teil des Grundes. Der andere Teil ist, weil eine Referenz initialisiert werden muss und es keinen Standardkonstruktor hat.

Gibt es mehr Typen, die in der Initialisierungsliste des Konstruktors initialisiert werden müssen?

Jeder Typ, der keinen Zuweisungsoperator (sei es kopieren oder verschieben) oder Standardkonstruktor hat. Dies beinhaltet natürlich (ist aber nicht beschränkt auf) const Mitglieder, da sie nicht mehr geändert werden können, sobald sie erstellt wurden.


Als Faustregel sollten Sie (fast) immer lieber Ihre Mitglieder in den Konstruktor der Initialisierungsliste initialisiert werden: warum Abfallzyklen erster Standard Konstruieren eines Objekts und auch dann nur, um es zuweisen (wenn dies auch ist möglich), wenn Sie es überhaupt richtig konstruieren könnten?

+1

Ich schäme mich wirklich, das zu fragen, aber ein Referenztyp hat keinen Zuweisungsoperator? – Billie

+3

@ user1798362 nein, ein Verweis es nur ein Alias ​​für etwas anderes. Wenn Sie einer Referenz "zuweisen", ordnen Sie sie wirklich dem Objekt zu, auf das sie sich bezieht. – juanchopanza

+0

Wie ich dachte. Vielen Dank! – Billie

3

Muss in der Errichterinitialisierungsliste ein Referenztyp für einen Klassenmember initialisiert werden?

Ja.

Ist das irgendwie damit zu tun, dass ein Referenztyp niemals neu zugewiesen werden kann?

Ja, plus die Tatsache, dass es keine "Null" oder Standardkonstruktion für eine Referenz gibt. Es ist ein Alias ​​für ein anderes Objekt, und es muss von Anfang an daran gebunden sein.Sie können dies nicht tun (das ist innerhalb einer Klassendefinition nicht):

int main() 
{ 
    int& iref; // ERROR 
    int i = 42; 
    int& iref2 = i; // OK 
} 

weil iref muss alias etwas.

+0

Danke für dieses Beispiel, jetzt habe ich es total! – Billie

-1
Must any class-member reference type be initialized in the constructor initialization list? 

Ja, wir sollten immer die Initialisierungsliste verwenden, um Referenzelemente einer Klasse zu initialisieren.

If so, why? Is that related somehow to the fact that a reference type can never be reassigned? 

Ein Konstruktor hat zwei Phasen, nämlich Initialisierung und Berechnung. Selbst wenn Sie die Initialisierungsliste für einen Datenmember nicht verwenden, initialisiert der Compiler sie mit einem zufälligen Wert. Und in der Berechnungsphase, die typischerweise mit dem '{' des Konstruktor-Körpers beginnt, wenn Sie eine Zuweisung machen, wird sich der Compiler beschweren, da das Referenz-Element bereits initialisiert wurde. Ihre einzige Chance, ein solches Member zu initialisieren, ist also die Konstruktorinitialisierungsliste.

Are there more types that must be initialized in constructor initialization list? 

Ja, const Datenelemente sind der andere Typ, für den Sie eine Initialisierungsliste benötigen.

+0

Der Compiler beklagt sich nicht wegen der Zuweisung (Zuweisung zu einer Referenz ist tatsächlich dem referenzierten Objekt zugewiesen, es gibt kein Problem damit) oder weil die Referenz bereits initialisiert ist, sondern weil sie * nicht initialisiert wurde (was illegal ist). – syam

Verwandte Themen