2017-03-10 1 views
1

I definiert Visual Studio bin mit 2013C++ Benutzer leer Standardkonstruktors vs impliziten oder default-ed Standardkonstruktors

Ich habe den folgenden Code

class Foo{ 
public: 
    Foo(){}; 
    Foo* fPtr; 
    float f; 
}; 

int main() 
{ 
    Foo foo1; // No Warning. fPtr is initialized to NULL, f is set to 0.0. 
    Foo foo2(foo1); // Compiles fine. Uses compiler generated copy constructor 
    return 0; 
} 

nun den gleichen Code betrachten, aber ohne den Benutzer definiert Standardkonstruktor.

class Foo{ 
public: 
       // No user defined default constructor, or equivalently 
       // Foo() = default; 
    Foo* fPtr; 
    float f; 
}; 

int main() 
{ 
    Foo foo1; // Neither fPtr nor f are initialized, both contain garbage. 
    //Foo foo2(foo1); // error C4700: uninitialized local variable 'foo1' used 
    return 0; 
} 

Ich dachte, dass der Benutzer definiert Standardkonstruktor und der implizit Standardkonstruktors definiert äquivalent sind, aber es scheint mir, sind sie nicht.

Wie genau arbeitet der Compiler Standardkonstruktor?

Nach diesem Fall bin ich vorsichtig gegen die Verwendung von Compiler definierten Standardkonstruktoren und immer meine eigenen, obwohl manchmal leer Standardkonstruktoren. Versteh ich etwas falsch?

Antwort

5

Bei der Implementierung funktioniert die implicitly-defined default constructor die gleiche Sache wie der benutzerdefinierte Konstruktor mit leeren Körper und leere Initialisierungsliste.

Wenn die implizit deklarierten Standardkonstruktors nicht als gelöscht definiert sind, definiert ist (das heißt, eine Funktion Körper erzeugt und kompiliert) durch den Compiler, wenn ODR-verwendet wird, und es hat genau die gleiche Wirkung wie ein benutzerdefinierter Konstruktor mit leerem Body und leerer Initialisierungsliste.

Und

Foo foo1; // No Warning. fPtr is initialized to NULL, f is set to 0.0. 

Nein, nicht nur für das zweite Codebeispiel, auch für das erste Codebeispiel foo1.fPtr und foo1.f werden nicht initialisiert; Der leere benutzerdefinierte Konstruktor initialisiert überhaupt keine Member.

Und über die Compiler-Warnung, es scheint, dass MSVS denkt, wenn ein benutzerdefinierter Konstruktor bereitgestellt und aufgerufen wird, dann könnte das Objekt angenommen werden, dass initialisiert wurden. Aber Sie müssen sicherstellen, dass der Konstruktor das tut, was Sie erwartet haben oder nicht.

Beachten Sie, dass sie noch einige subtile verschiedene Nebenwirkungen haben; wie für list initialization und value intialization, (aber nicht default initialization hier verwendet). z.B. für

Foo foo1{}; 

Dann für den ersten Fall wird der benutzerdefinierte Standardkonstruktor aufgerufen; da es nichts tut foo1.fPtr und foo1.f wird immer noch nicht initialisiert sein; Aber für den zweiten Fall wird aggregate initialization ausgeführt (wegen des fehlenden benutzerdefinierten Konstruktors), dann werden foo1.fPtr und foo1.f wertinitialisiert. d.h. foo1.fPtr wird initialisiert auf nullptr, foo1.f wird initialisiert auf 0.

+0

Ich verstehe nicht ganz, was Sie mit "Nein" meinen. Selbst für das erste Codebeispiel sind foo1.fPtr und foo1.f nicht initialisiert, der benutzerdefinierte Konstruktor tut nichts. ". Tatsache ist, dass im ersten Fall der benutzerdefinierte Konstruktor mit 'Foo foo1;' und 'Foo foo1 {}' aufgerufen wird und die Member korrekt auf ihre Standardwerte, d. H. NULL und 0, initialisiert werden.0, also nehme ich an, dass der benutzerdefinierte Konstruktor tatsächlich etwas tut. –

+2

@Hrachya_h Nein, sie sind nicht initialisiert, zum Beispiel http://rextester.com/JVFH58493. – songyuanyao

+1

'Foo foo1;' Initialisiert NICHT die Member in beiden Beispielen, da keine Initialisierung vorhanden ist. Wenn sie auf Nullen initialisiert werden, ist es ein zufälliges undefiniertes Verhalten des Compilers. Es ist NICHT garantiert in diesen Beispielen. –

Verwandte Themen