2015-10-31 5 views
8

Wenn ein C++ - Konstruktor für ein Objekt mit statischer Speicherdauer ein Member nicht initialisiert, ist das erforderlich, um die vorherige Nullinitialisierung beizubehalten, oder belässt es das Element mit einem unbestimmten Wert?Wird bei der C++ - Standardinitialisierung die vorherige Nullinitialisierung beibehalten?

Meine Lesung der C++ - Spezifikation ist, dass es sich widerspricht.

Beispiel:

#include <iostream> 

struct Foo { Foo(); int x; } object; 

Foo::Foo() { } 

int main() { std::cout << object.x << std::endl; } 

Der Konstruktor Foo() nicht explizit das Element object.x initialisieren, so nach dem Vermerk in 12.6.2 Absatz 8:

das Mitglied unbestimmter Wert.

Aber durch die Details der verschiedenen Initialisierungen funktioniert, scheint dies zu inkorrekt zu sein. Das Element object.x wird auf Null initialisiert, da es statische Speicherdauer hat, und dann kann ich nichts sehen, was das ändert.

In Bezug auf den Konstruktor, der Text in 12.6.2, das gilt, ist:

das Unternehmen ist default-initialisiert.

In 8.5 Absatz 7 der betreffende Fall von Standardinitialisierung ist:

... keine Initialisierung durchgeführt wird

, die ich meine gelesen, dass die vorherige Null-Initialisierung nicht durch die Standard-Initialisierung geändert.

Vermisse ich einen anderen Text, der alle Mitglieder am Beginn des Konstruktoraufrufs auf "unbestimmter Wert" zurücksetzt?

fand ich verschiedene andere Fragen auf Stackoverflow in Bezug auf Null-Initialisierung und default-Initialisierung, aber ich konnte nicht, dass analysiert, was passiert, wenn Standard-Initialisierung folgt einig frühe Initialisierung der gleichen Einheit sehen.

In diesem Fall gibt es wahrscheinlich keinen praktischen Effekt. Aber muss der Compiler in einem komplexeren Konstruktor, bei dem einige Member initialisiert wurden und andere nicht, genau nachverfolgen, welche Bytes/Bits initialisiert wurden? Oder kann er das ganze Objekt initialisieren (zB den Konstruktor zu einem memset() - Aufruf vereinfachen))

+2

Ich entfernte meine Antwort, weil es eine Wendung gibt, über die ich mir nicht sicher bin: 'Foo' ist ein Objekt mit nicht-trivialer Initialisierung, was bedeutet, dass seine Lebensdauer erst begonnen hat, wenn der Konstruktor fertig ist. Ich bin mir also nicht sicher über die Werte seiner Mitglieder. Bevor der Konstruktor mit der Ausführung begonnen hat, können Sie möglicherweise nicht einmal auf sie zugreifen (durch normative Regeln), so dass es mir schwer fällt, zu diesem Zeitpunkt Wertwerte (Null) zu speichern. Ganz zu schweigen von der Existenz eines Objekts in der ersten Ort. –

+0

@LightnessRacesinOrbit re "Eh nein, wenn es nur im Entwurf ist, dann ist es nicht in einem Standard und sollte nicht verlässlich sein" .. dann haben wir es schwer, den Code der realen Welt zu schreiben, denke ich. Angesichts wie viele Fehlerberichte (einige noch offen) versuchen, Fehler im Standard zu beheben :) Zum Beispiel, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#191 –

+0

@ ↔ JohannesSchaub Ich glaube, deine gelöschte Antwort war eine gute Antwort. Es fällt mir schwer, eine Null-Initialisierung sinnvoll zu finden, wenn das Objekt für die statische Speicherdauer vor dem Konstruktoraufruf vollständig nicht existiert. Z.B., wäre es für einen Compiler im Hintergrund, "object" durch einen versteckten Zeiger zu ersetzen, der durch "new Foo()" initialisiert wird? – user1998586

Antwort

3

Defect report 1787 führen zu der in N3914 dokumentierten Änderung, die applied to the draft standard for C++14 ist. Welche ändern [dcl.init] Ziffer 12 aus:

Wenn kein Initialisierer für ein Objekt angegeben wird, ist das Objekt default-initialisiert; Wenn keine Initialisierung durchgeführt wird, hat ein Objekt mit der automatischen oder dynamischen Speicherdauer einen unbestimmten Wert. [Hinweis: Objekte mit statischer oder Thread-Speicherdauer sind 0-initialisiert, siehe 3.6.2.- Endnote]

zu:

Wenn kein Initialisierer für ein Objekt angegeben wird, ist das Objekt default-initialisiert. Bei Lagerung für ein Objekt mit automatischer oder dynamischer Lagerdauer erhalten wird, hat das Objekt einen unbestimmten Wert, und wenn keine Initialisierung für das Objekt durchgeführt wird, dass Objekt behält einen unbestimmten Wert, bis dieser Wert ersetzt (5,17 [expr.ass]). [Hinweis: Objekte mit statischem oder Thread-Speicher Dauer sind Null-initialisiert, siehe 3.6.2 [basic.start.init]. -Ende Anmerkung] Wenn ein unbestimmter Wert durch eine Auswertung erzeugt wird, das Verhalten außer in den folgenden Fällen nicht definiert ist:

[...]

Diese klar nur die unbestimmte Wert Situation machen tritt für Objekte mit automatischer oder dynamischer Speicherdauer auf. Da dies über einen Fehlerbericht angewendet wurde, gilt es wahrscheinlich auch für C++ 11, da der Fehlerbericht vor der Übernahme von C++ 14 aufgetreten ist, aber auch noch weiter zurückgehen könnte. Die Regeln, wie weit ein Defekt zurückgehen soll, waren mir nie klar.

Seit Platzierung neu wurde in den Kommentaren, die gleiche Änderung auch Abschnitt modifizierte [expr.new], so dass der unbestimmte Wert Abschnitt einen Kommentar gebracht:

Wenn der neue-initializer weggelassen wird, das Objekt ist standardmäßig initialisiert (8.5 [dcl.init]); ob. [Hinweis: Wenn keine Initialisierung durchgeführt wird, hat das Objekt einen unbestimmten Wert. -Ende note]

Der Anfang des Abschnitts sagt:.

[...] Entities durch einen neuen Ausdruck erstellt haben dynamische Speicher Dauer (3.7.4) [... ]

, die die Änderungen in Abschnitt [dcl.init] anzuwenden ausreichend zu sein scheinen.

Diese Änderung war auch interessant, da vor dieser Änderung der Begriff indeterminate value was not defined im C++ - Standard.

+0

Die neue Formulierung ist in diesem Fall sehr klar. Es ist nicht ganz so klar für ein Placement-neu (die Regeln für welche Speicherdauer gelten?). Meine Lesung dort ist, dass jede vorherige Initialisierung ist irrelevant und das Verhalten ist wie automatische/dynamische Speicherdauer. Wenn Sie zum Beispiel ein char-Array mit statischer Dauer haben und dann placement-new aufrufen, um ein Objekt im Array zu erstellen, ist die Null-Initialisierung des char-Arrays irrelevant? – user1998586

+1

@ user1998586 aktualisierte Antwort. –

Verwandte Themen