2012-06-24 4 views
26

OK, Elementvariablen can be used, um andere Elementvariablen in einer Initialisierungsliste zu initialisieren (wobei die Initialisierungsreihenfolge beachtet wird usw.). Was ist mit Mitgliedsfunktionen? Um genau zu sein, ist dieses Snippet nach dem C++ - Standard legal?können Memberfunktionen zum Initialisieren von Elementvariablen in einer Initialisierungsliste verwendet werden?

struct foo{ 
    foo(const size_t N) : N_(N), arr_(fill_arr(N)) { 
    //arr_ = fill_arr(N); // or should I fall back to this one? 
    } 

    std::vector<double> fill_arr(const size_t N){ 
    std::vector<double> arr(N); 
    // fill in the vector somehow 
    return arr; 
    } 

    size_t N_; 
    std::vector<double> arr_; 
    // other stuff 
}; 
+0

Die Frage ist gut, aber das Code-Beispiel ist etwas künstlich. Was hindert Sie daran, 'fill_arr' als' statisch' zu deklarieren und keinen Zweifel daran zu haben, dass es legal ist? –

+0

Wäre das Thread-sicher? Ich meine, da ist ein Vektor local 'fill_arr', wenn das" statisch "ist, soll ich es durch eine Art Mutex schützen? –

+2

Der 'std :: vector arr' hat _automatic storage_, also würde es für jeden Aufruf der Funktion' fill_arr' eine Instanz geben. Das ist einfach _C++ _... –

Antwort

30

Ja, Ihre Verwendung der Elementfunktion in der Initialisierungsliste ist gültig und entspricht dem Standard.

Datenelemente werden in der Reihenfolge ihrer Deklaration initialisiert (und deshalb sollten sie in der Initialisierungsliste in der Reihenfolge ihrer Deklaration angezeigt werden - die Regel, die Sie in Ihrem Beispiel befolgt haben). N_ wird zuerst initialisiert und Sie könnten dieses Datenelement an fill_arr übergeben haben. fill_arr wird vor dem Konstruktor aufgerufen, aber da diese Funktion nicht auf nicht initialisierte Datenelemente zugreift (sie greift überhaupt nicht auf Datenelemente zu), wird ihr Aufruf als sicher betrachtet.

Hier sind einige relevante excepts aus dem aktuellen Entwurf (N3242 = 11-0012) der Standard C++:

§ 12.6.2.13: Member-Funktionen (einschließlich virtueller Elementfunktionen, 10.3) aufgerufen werden kann für ein Objekt im Aufbau. (...) Wenn diese Operationen jedoch in einem ctor-Initialisierer (oder in einer Funktion , die direkt oder indirekt von einem ctor-Initialisierer aufgerufen wird) ausgeführt werden, müssen alle mem-Initialisierer für Basisklassen haben abgeschlossen, ist das Ergebnis der Operation undefiniert. Beispiel:

class A { public: A(int); }; 

class B : public A { 
    int j; 
public: 
    int f(); 
    B() : A(f()), // undefined: calls member function 
       // but base A not yet initialized 
    j(f()) { } // well-defined: bases are all initialized 
}; 

class C { 
public: 
    C(int); 
}; 

class D : public B, C { 
    int i; 
public: 
    D() : C(f()), // undefined: calls member function 
       // but base C not yet initialized 
    i(f()) { } // well-defined: bases are all initialized 
}; 

§12.7.1: Für ein Objekt mit einem nicht-trivialen Konstruktor, unter Bezugnahme auf jede nicht-statische Element oder Basisklasse des Objektes vor dem Konstruktor beginnt Ausführungsergebnisse in undefiniertes Verhalten. Beispiel

struct W { int j; }; 
struct X : public virtual W { }; 
struct Y { 
    int *p; 
    X x; 
    Y() : p(&x.j) { // undefined, x is not yet constructed 
    } 
}; 
3

Beim Initialisieren Objekte in der Initialisierungsliste wird das Objekt noch nicht vollständig aufgebaut ist.
Wenn diese Funktion versucht, auf den Teil des Objekts zuzugreifen, der noch nicht konstruiert ist, dann ist das ein undefiniertes Verhalten, ansonsten ist es in Ordnung.
siehe this answer.

+0

Das ist genau das Fleisch der Frage: Was sind die Regeln für die Konstruktionsordnung für die Mitgliedsfunktionen? –

+0

@Zhenya siehe dies :: http://Stackoverflow.com/a/3899583/981787 – Eight

+0

Korrigieren Sie mich, wenn ich falsch liege: die Frage, auf die Sie sich beziehen, befasst sich mit Elementvariablen und nicht mit Elementfunktionen. Implizieren Sie, dass Mitgliedsfunktionen den gleichen Regeln folgen? Zum einen reklamiert gcc 4.4.3 nicht, wenn ich die Reihenfolge der Deklarationen von 'arr_' ​​und' fill_arr() 'umschalte, während es Warnungen ausgibt, wenn die Reihenfolge in der init-Liste nicht mit der Reihenfolge der Deklarationen übereinstimmt . –

Verwandte Themen