Wenn "Test" eine gewöhnliche Klasse ist, gibt es einen Unterschied zwischen:
Test* test = new Test;
et
Test* test = new Test();
Wenn "Test" eine gewöhnliche Klasse ist, gibt es einen Unterschied zwischen:
Test* test = new Test;
et
Test* test = new Test();
Die Regeln für new
sind analog zu dem, was passiert, wenn Sie ein Objekt mit automatischer Speicherdauer initialisieren (obwohl die Syntax wegen der lästigen Parsen etwas anders sein kann).
Wenn ich sage:
int my_int; // default-initialize indeterminate (non-class type)
Entonces my_int
hat einen unbestimmten Wert, da es sich um eine Nicht-Klassenart handelt. Alternativ kann ich auch eine Wertinitialisierung durchführen my_int
(die für Nicht-Klassentypen null-initialisiert) wie folgt:
int my_int{}; // value-initialize zero-initialize (non-class type)
(Natürlich kann ich nicht mit ()
denn das wäre eine Funktionsdeklaration, aber int()
funktioniert genauso wie int{}
um ein Provisorium zu konstruieren).
Für Klassenarten hingegen:
Thing my_thing; // default-initialize default ctor (class type)
Thing my_thing{}; // value-initialize default-initialize default ctor (class type)
Der Standardkonstruktor wird aufgerufen, um eine Thing
keine Ausnahmen.
Die Regeln lauten also mehr oder weniger:
{}
) oder standard-initialisiert (ohne {}
). (Bei der Wertinitialisierung gibt es ein zusätzliches vorheriges Nullsetzungsverhalten, aber der Standardkonstruktor hat immer das letzte Wort).{}
verwendet?
Diese Regeln lauten genau new
Syntax, mit der zusätzlichen Regel, dass ()
kann ersetzt werden durch {}
denn new
wird nie als Funktionsdeklaration geparst. Also:
int* my_new_int = new int; // default-initialize indeterminate (non-class type)
Thing* my_new_thing = new Thing; // default-initialize default ctor (class type)
int* my_new_zeroed_int = new int(); // value-initialize zero-initialize (non-class type)
my_new_zeroed_int = new int{}; // ditto
my_new_thing = new Thing(); // value-initialize default-initialize default ctor (class type)
(Diese Antwort berücksichtigt konzeptionelle Änderungen in C++11, die in der oberen Antwort nicht enthalten sind; insbesondere wird eine neue Skalar- oder POD-Instanz, die mit einem unbestimmten Wert enden würde, nun technisch standardinitialisiert (was bei POD-Typen technisch einen trivialen Standardkonstruktor aufruft). Dies führt zwar nicht zu großen praktischen Änderungen im Verhalten, vereinfacht aber die Regeln etwas).
Ich habe unten einige Beispielcodes geschrieben, als Ergänzung zu der Antwort von Michael Burr:
#include <iostream>
struct A1 {
int i;
int j;
};
struct B {
int k;
B() : k(4) {}
B(int k_) : k(k_) {}
};
struct A2 {
int i;
int j;
B b;
};
struct A3 {
int i;
int j;
B b;
A3() : i(1), j(2), b(5) {}
A3(int i_, int j_, B b_): i(i_), j(j_), b(b_) {}
};
int main() {
{
std::cout << "Case#1: POD without ()\n";
A1 a1 = {1, 2};
std::cout << a1.i << " " << a1.j << std::endl;
A1* a = new (&a1) A1;
std::cout << a->i << " " << a->j << std::endl;
}
{
std::cout << "Case#2: POD with ()\n";
A1 a1 = {1, 2};
std::cout << a1.i << " " << a1.j << std::endl;
A1* a = new (&a1) A1();
std::cout << a->i << " " << a->j << std::endl;
}
{
std::cout << "Case#3: non-POD without ()\n";
A2 a1 = {1, 2, {3}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A2* a = new (&a1) A2;
std::cout << a->i << " " << a->j << " " << a->b.k << std::endl;
}
{
std::cout << "Case#4: non-POD with ()\n";
A2 a1 = {1, 2, {3}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A2* a = new (&a1) A2();
std::cout << a->i << " " << a->j << " " << a1.b.k << std::endl;
}
{
std::cout << "Case#5: user-defined-ctor class without ()\n";
A3 a1 = {11, 22, {33}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A3* a = new (&a1) A3;
std::cout << a->i << " " << a->j << " " << a->b.k << std::endl;
}
{
std::cout << "Case#6: user-defined-ctor class with ()\n";
A3 a1 = {11, 22, {33}};
std::cout << a1.i << " " << a1.j << " " << a1.b.k << std::endl;
A3* a = new (&a1) A3();
std::cout << a->i << " " << a->j << " " << a1.b.k << std::endl;
}
return 0;
}
/*
output with GCC11.1(C++20)
Case#1: POD without ()
1 2
1 2
Case#2: POD with ()
1 2
0 0
Case#3: non-POD without ()
1 2 3
1 2 4
Case#4: non-POD with ()
1 2 3
0 0 4
Case#5: user-defined-ctor class without ()
11 22 33
1 2 5
Case#6: user-defined-ctor class with ()
11 22 33
1 2 5
*/
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.