Frage Initialisiert der Standardkonstruktor integrierte Typen?


Initialisiert der Standardkonstruktor (vom Compiler erstellt) die integrierten Typen?


144


Ursprung


Antworten:


Der implizit (durch den Compiler) definierte Standardkonstruktor einer Klasse initialisiert keine Member von eingebauten Typen.

Es ist jedoch zu beachten, dass die Initialisierung einer Instanz der Klasse in einigen Fällen auf andere Weise erfolgen kann. Nicht per Standardkonstruktor oder gar über Konstruktor.

Zum Beispiel gibt es eine weit verbreitete falsche Überzeugung, dass für die Klasse C die Syntax C() ruft immer den Standardkonstruktor auf. In Wirklichkeit jedoch die Syntax C() führt so genannte Wert-Initialisierung der Klasseninstanz. Es wird nur den Standardkonstruktor aufrufen, wenn dies der Fall ist Benutzer deklariert. (Das ist in C ++ 03. In C ++ 98 - nur wenn die Klasse nicht-POD ist). Wenn die Klasse keinen vom Benutzer deklarierten Konstruktor hat, dann wird der C() ruft den vom Compiler bereitgestellten Standardkonstruktor nicht auf, sondern führt eine spezielle Art der Initialisierung durch, bei der der Konstruktor nicht beteiligt ist C überhaupt. Stattdessen wird jedes Mitglied der Klasse direkt initialisiert. Bei eingebauten Typen führt dies zu einer Null-Initialisierung.

Zum Beispiel, wenn Ihre Klasse keinen vom Benutzer deklarierten Konstruktor hat

class C { 
  int x;
};

dann wird der Compiler implizit einen bereitstellen. Der vom Compiler bereitgestellte Konstruktor wird nichts tun, was bedeutet, dass er nicht initialisiert wird C::x

C c; // Compiler-provided default constructor is used
// Here `c.x` contains garbage

Trotzdem die folgenden Initialisierungen werden Null initialisieren x weil sie das Explizite verwenden () Initialisierer

C c = C(); // Does not use default constructor for `C()` part
           // Uses value-initialization feature instead
assert(c.x == 0);

C *pc = new C(); // Does not use default constructor for `C()` part
                 // Uses value-initialization feature instead
assert(pc->x == 0);

Das Verhalten von () Initialisierer unterscheidet sich in einigen Punkten zwischen C ++ 98 und C ++ 03, aber nicht in diesem Fall. Für die oben genannte Klasse C Es wird dasselbe sein: () Initialisierer führt Null Initialisierung von C::x.

Ein anderes Beispiel für die Initialisierung, die ohne Beteiligung des Konstruktors ausgeführt wird, ist natürlich die Aggregat-Initialisierung

C c = {}; // Does not use any `C` constructors at all. Same as C c{}; in C++11.
assert(c.x == 0);

C d{}; // C++11 style aggregate initialization.
assert(d.x == 0);

143



Für alle praktischen Zwecke - nein.


Bei Implementierungen, die technisch dem C ++ - Standard entsprechen, lautet die Antwort jedoch, dass es darauf ankommt, ob das Objekt POD ist oder nicht, und wie Sie es initialisieren. Nach dem C ++ - Standard:

MyNonPodClass instance1;//built in members will not be initialized
MyPodClass instance2;//built in members will be not be initialized
MyPodClass* instance3 = new MyPodClass;//built in members will not be initialized
MyPodClass* instance3 = new MyPodClass() ;//built in members will be zero initialized

In der realen Welt wird dies jedoch nicht gut unterstützt, also benutzen Sie es nicht.


Die relevanten Teile der Norm sind Abschnitt 8.5.5 und 8.5.7


17



Ich bin nicht ganz sicher, was du meinst, aber:

struct A { int x; };

int a; // a is initialized to 0
A b;   // b.x is initialized to 0

int main() {
    int c;         // c is not initialized
    int d = int(); // d is initialized to 0

    A e;           // e.x is not initialized
    A f = A();     // f.x is initialized to 0
}

In jedem Fall, in dem ich sage "nicht initialisiert" - Sie könnten feststellen, dass Ihr Compiler gibt es einen konsistenten Wert, aber der Standard erfordert es nicht.

Eine Menge Hand-waving wird herumgeworfen, auch von mir, darüber, wie eingebaute Typen "in Wirklichkeit" einen Standardkonstruktor haben. Eigentlich sind Standard-Initialisierung und -Wert-Initialisierung Begriffe im Standard definiert, die ich persönlich jedes Mal nachschlagen muss. Im Standard sind nur Klassen definiert, die einen impliziten Standardkonstruktor haben.


11



Gemäß dem Standard wird dies nicht ausgeführt, es sei denn, Sie initialisieren explizit in der Initialisierungsliste


1



Wie Vorredner gesagt haben - nein, sie sind nicht initialisiert.

Dies ist tatsächlich eine Quelle für wirklich seltsame Fehler, da moderne Betriebssysteme dazu neigen, neu zugewiesene Speicherbereiche mit Nullen zu füllen. Wenn Sie das erwarten, könnte es das erste Mal funktionieren. Wie auch immer Ihre Anwendung läuft, delete-ing und newObjekte werden Sie früher oder später in einer Situation enden, in der Sie Nullen erwarten, aber ein Nicht-Null-Rest von einem früheren Objekt sitzt.

Also, warum ist das dann, ist nicht alles newDaten neu vergeben? Ja, aber nicht immer vom Betriebssystem. Das OS neigt dazu, mit größeren Speicherblöcken zu arbeiten (z. B. 4 MB zu einer Zeit), so dass alle winzigen Ein-Wort-hier-drei-Bytes-Zuordnungen und Freigaben in uyserspace gehandhabt werden und somit nicht auf Null gesetzt werden.

PS. Ich schrieb "tend to", d. H. Sie können sich beim ersten Mal nicht einmal auf den Erfolg verlassen ...


1



Technisch initialisiert es sie - indem sie ihren Standardkonstruktor verwendet, der übrigens nichts anderes tut, als den Speicher für sie zuzuweisen.

Wenn Sie wissen wollten, ob sie für etwas gesund wie 0 festgelegt sind ints, dann ist die Antwort "Nein".


-3



Nein. Der Standardkonstruktor weist Speicher zu und ruft den Konstruktor ohne Argumente aller Eltern auf.


-6