new mit Initialisierung
Beim letzten Mal wurde mit dem new-Operator nur der Standardkonstruktor der betreffenden Klasse aufgerufen. Das ist in manchen Situationen etwas wenig...
Video
Code
Einzelnes Objekt mit Non-Standard-Konstruktor
#include <iostream>
class Greeter
{
public:
Greeter()
{
std::cout << "Greeter initialisiert\n";
}
Greeter(int x)
{
std::cout << "Greeter mit " << x << " initialisiert\n";
}
~Greeter()
{
std::cout << "Greeter zerstört\n";
}
};
int main()
{
Greeter *g = new Greeter(5);
std::cout << "Hier bin ich\n";
delete g;
}
Array-new mit Initialisierung
#include <iostream>
class Greeter
{
public:
Greeter()
{
std::cout << "Greeter initialisiert\n";
}
Greeter(int x)
{
std::cout << "Greeter mit " << x << " initialisiert\n";
}
~Greeter()
{
std::cout << "Greeter zerstört\n";
}
};
int main()
{
Greeter *gs = new Greeter[3] {Greeter(2), Greeter(5), Greeter(1) };
std::cout << "Greeter sind vorhanden\n";
delete[] gs;
std::cout << "Programmende\n";
}
Erklärung
Im Grunde keine Überraschung: für den einfachen Fall mit einem Einzelobjekt (der zugegebenermaßen auch der deutlich häufigere ist), sieht das ganze genauso aus, wie man es erwarten würde. Hinter dem Typen werden einfach in Form einer Parameterliste die notwendigen Daten zur Initialisierung angegeben und der Compiler setzt das dann in den geeigneten Konstruktoraufruf um.
Etwas komplexer wird es schon beim Array-new. C++98 und C++03 bieten hier
keine Möglichkeiten zur Angabe von anderen Konstruktoren an. Es können also nur
Typen in Arrays verpackt werden, die standardkonstruierbar sind. Ein gängiger
Workaround für diese Art von Problem ist eine Initialisierungsfunktion, die dann
in etwa so verwendet wird:
Typ *t = new Typ[10];
for (int i=0; i < 10; ++i) {
t[i].init(parameter1, parameter2);
}
Nachteil hier natürlich: wenn man bspw. ein API zur externen Nutzung baut, dann
kann man sich nie sicher sein, dass der Aufrufer auch wirklich an die
init-Funktion denkt.
C++11 geht hier einen Schritt weiter und bietet eine Syntax an, mit der man auch
Array-Elemente passend initialisieren kann: die Initialisierungsliste, wie im
zweiten Listing dargestellt. So, wie sie in der Liste auftauchen, werden die
Array-Elemente initialisiert. Das Thema "Initialisierungslisten" in C++ ist
eigentlich noch wesentlich größer. Dazu aber später noch ein Video. Einziger
Nachteil der Initialisierungsliste: sie kann keine dynamische Länge haben. Wenn
man also dynamische Arrays initialisiert, dann wird's wieder schwieriger. Dann
lugt die init-Funktion wieder um die Ecke...