Erzeugung bei Array sichergestellt?
-
Abend!
wenn ich ein Array von Objekten anlege:
Foo* f = new Foo[100];Ist dann garantiert, dass die Konstruktoren der Reihenfolge nach aufgerufen werden? Sprich wird IMMER das Objekt f[0] erzeugt, dann f[1], dann f[2] etc.?
-
Davon kannst du, soweit ich weiß, nicht ausgehen. Zumindest ist mir nichts im Standard bekannt das dir diese Reihenfolge wirklich garantiert.
Du kannst aber new für deine Anforderung überschreiben.
-
Matir schrieb:
wenn ich ein Array von Objekten anlege:
Foo* f = new Foo[100];Ist dann garantiert, dass die Konstruktoren der Reihenfolge nach aufgerufen werden? Sprich wird IMMER das Objekt f[0] erzeugt, dann f[1], dann f[2] etc.?
ja, das gilt im Übrigen für jedes Array, nicht nur für solche, die mit new erzeugt werden.
-
Ich denke nicht, dass man davon ausgehen kann. Unter der Annahme, dass Foo non-POD ist (sonst stellt sich die Frage gar nicht), gilt nach 5.3.4 (15):
ISO/IEC 14882:2003 5.3.4 (15) schrieb:
A new-expression that creates an object of type T initializes that object as follows:
— If the new-initializer is omitted:
— If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized (8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.Und default-initialized ist nach 8.5 (5) wie folgt zu verstehen:
ISO/IEC 14882:2004 8.5 (5) schrieb:
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, the object is zero-initialized....und das ist auch alles, was ich im Standard dazu finde. Über die Reihenfolge steht nirgends ein Wort geschrieben - es scheint fast so, als bliebe das undefiniert.
operator new zu überladen dürfte hier auch nicht helfen, da der ja nur für die Speicherbesorgung zuständig ist. Man könnte wohl mit placement-new entsprechendes Verhalten erzwingen:
char *ptr = new char[sizeof(Foo) * 100]; for(std::size_t i = 0; i < 100; ++i) { new(ptr + i * sizeof(Foo)) Foo(); } Foo *f = reinterpret_cast<Foo*>(ptr);aber das ist natürlich alles andere als hübsch. Mit std::vector könnte man den Speicher vorher reservieren und 100 mal ein default-initialisiertes Objekt push_backen; das würde ich ggf. allerdings durch einen Profiler jagen, um zu sehen, ob Performance-Einbußen entstehen.
Wieso ist das überhaupt von Bedeutung?
-
camper schrieb:
ja, das gilt im Übrigen für jedes Array, nicht nur für solche, die mit new erzeugt werden.
Bin natürlich geneigt dem sofort zu glauben, weil es aus deinem Munde kommt. Könntest du trotzdem noch die Erklärung, den Paragrafen hinzuliefern?
-
When an array of class objects is initialized (either explicitly or implicitly), the constructor shall be called
for each element of the array, following the subscript order; see 8.3.4. [Note: destructors for the array elements
are called in reverse order of their construction. ]
-
Das wäre dann §12.6(3).
Danke dir 12.6!
