Initialisierung mit geschweiften Klammern

Es ist nicht immer notwendig, einen Konstruktor für einen class, insbesondere diejenigen zu definieren, die relativ einfach sind. Benutzer können Objekte eines class oder struct mithilfe einer einheitlichen Initialisierung initialisieren, wie im folgenden Beispiel gezeigt:

// no_constructor.cpp
// Compile with: cl /EHsc no_constructor.cpp
#include <time.h>

// No constructor
struct TempData
{
    int StationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

// Has a constructor
struct TempData2
{
    TempData2(double minimum, double maximum, double cur, int id, time_t t) :
       stationId{id}, timeSet{t}, current{cur}, maxTemp{maximum}, minTemp{minimum} {}
    int stationId;
    time_t timeSet;
    double current;
    double maxTemp;
    double minTemp;
};

int main()
{
    time_t time_to_set;

    // Member initialization (in order of declaration):
    TempData td{ 45978, time(&time_to_set), 28.9, 37.0, 16.7 };

    // When there's no constructor, an empty brace initializer does
    // value initialization = {0,0,0,0,0}
    TempData td_emptyInit{};

    // Uninitialized = if used, emits warning C4700 uninitialized local variable
    TempData td_noInit;

    // Member declaration (in order of ctor parameters)
    TempData2 td2{ 16.7, 37.0, 28.9, 45978, time(&time_to_set) };

    return 0;
}

Wenn ein class oder struct kein Konstruktor vorhanden ist, stellen Sie die Listenelemente in der Reihenfolge bereit, in der die Member deklariert classwerden. Wenn der Konstruktor vorhanden class ist, stellen Sie die Elemente in der Reihenfolge der Parameter bereit. Wenn ein Typ über einen Standardkonstruktor verfügt, entweder implizit oder explizit deklariert, können Sie die Klammerninitialisierung mit leeren geschweiften Klammern verwenden, um ihn aufzurufen. So kann beispielsweise folgendes class initialisiert werden, indem leere und nicht leere geschweifte Klammern initialisiert werden:

#include <string>
using namespace std;

class class_a {
public:
    class_a() {}
    class_a(string str) : m_string{ str } {}
    class_a(string str, double dbl) : m_string{ str }, m_double{ dbl } {}
double m_double;
string m_string;
};

int main()
{
    class_a c1{};
    class_a c1_1;

    class_a c2{ "ww" };
    class_a c2_1("xx");

    // order of parameters is the same as the constructor
    class_a c3{ "yy", 4.4 };
    class_a c3_1("zz", 5.5);
}

Wenn eine Klasse nicht standardmäßige Konstruktoren enthält, ist die Reihenfolge, in der Klassenmember im Initialisierer für geschweifte Klammern angezeigt werden, die Reihenfolge, in der die entsprechenden Parameter im Konstruktor angezeigt werden, und nicht die Reihenfolge, in der die Member deklariert werden (wie für class_a im vorherigen Beispiel). Wenn der Typ keinen deklarierten Konstruktor aufweist, müssen Memberinitialisierer in der Klammerninitialisierung in der gleichen Reihenfolge angezeigt werden wie sie deklariert werden. In diesem Fall können Sie so viele der öffentlichen Mitglieder wie gewünscht initialisieren, aber Sie können kein Mitglied überspringen. Das folgende Beispiel zeigt die Reihenfolge, die in der Initialisierung von geschweiften Klammern verwendet wird, wenn kein deklarierter Konstruktor vorhanden ist:

class class_d {
public:
    float m_float;
    string m_string;
    wchar_t m_char;
};

int main()
{
    class_d d1{};
    class_d d1{ 4.5 };
    class_d d2{ 4.5, "string" };
    class_d d3{ 4.5, "string", 'c' };

    class_d d4{ "string", 'c' }; // compiler error
    class_d d5{ "string", 'c', 2.0 }; // compiler error
}

Wenn der Standardkonstruktor explizit deklariert, aber als gelöscht markiert ist, kann die initialisierung leerer geschweifte Klammern nicht verwendet werden:

class class_f {
public:
    class_f() = delete;
    class_f(string x): m_string { x } {}
    string m_string;
};
int main()
{
    class_f cf{ "hello" };
    class_f cf1{}; // compiler error C2280: attempting to reference a deleted function
}

Sie können die Klammerninitialisierung überall verwenden, wo Sie normalerweise initialisieren würden, z. B. als Funktionsparameter oder als Rückgabewert oder mit dem new Schlüsselwort (keyword):

class_d* cf = new class_d{4.5};
kr->add_d({ 4.5 });
return { 4.5 };

Im /std:c++17 Modus und später sind die Regeln für die Initialisierung leerer geschweifte Klammern etwas restriktiver. Siehe abgeleitete Konstruktoren und erweiterte Aggregatinitialisierung.

initializer_list-Konstruktoren

Die initializer_list Klasse stellt eine Liste von Objekten eines angegebenen Typs dar, die in einem Konstruktor und in anderen Kontexten verwendet werden können. Sie können ein initializer_list-Objekt durch Verwenden der Initialisierung mit geschweiften Klammern erstellen:

initializer_list<int> int_list{5, 6, 7};

Wichtig

Um diese Klasse zu verwenden, müssen Sie den <initializer_list> Header einschließen.

Ein initializer_list-Objekt kann kopiert werden. In diesem Fall sind die Member der neuen Liste Verweise auf die Member der ursprünglichen Liste:

initializer_list<int> ilist1{ 5, 6, 7 };
initializer_list<int> ilist2( ilist1 );
if (ilist1.begin() == ilist2.begin())
    cout << "yes" << endl; // expect "yes"

Die Standard-Bibliothekscontainerklassen sowie string, wstring und regex verfügen über initializer_list-Konstruktoren. Die folgenden Beispiele zeigen, wie die Initialisierung mit geschweiften Klammern mit diesen Konstruktoren durchgeführt wird:

vector<int> v1{ 9, 10, 11 };
map<int, string> m1{ {1, "a"}, {2, "b"} };
string s{ 'a', 'b', 'c' };
regex rgx{ 'x', 'y', 'z' };

Siehe auch

Klassen und Strukturen
Konstruktoren