Wir können die Variable in C++ auf zwei Arten initialisieren
Einer:
int abc = 7;
Zwei:
int abc {7};
Was ist der Unterschied zwischen diesen beiden Methoden? Behandelt der Compiler sie anders, oder gibt es einen Unterschied in der Art und Weise, wie der Code ausgeführt wird?
Kurzfassung
Initialisierung über {..}
ist die Listeninitialisierung, die einschränkende Konvertierungen verbietet. Zum Beispiel, wenn LLONG_MAX
ist der Maximalwert von an long long int
und dein int
kann das nicht darstellen:
int x = LLONG_MAX; // probably accepted with a warning
int x {LLONG_MAX}; // error
Ähnlich:
long long y = /*something*/;
int x = y; // accepted, maybe with a warning
int x {y}; // error
Lange Version
Eine Initialisierung des Formulars
T x = a;
ist Kopie-Initialisierung; eine Initialisierung einer der beiden Formen
T x(a);
T x{a};
ist Direkt-Initialisierung, [dcl.init]/15-16.
[dcl.init]/14 sagt dann:
Die Form der Initialisierung (mit Klammern bzw =
) ist im Allgemeinen unbedeutend, spielt aber eine Rolle, wenn der Initialisierer oder die zu initialisierende Entität einen Klassentyp hat; siehe unten.
Also für Nicht-Klassen-Typen, die bilden der Initialisierung spielt keine Rolle. Es gibt jedoch einen Unterschied zwischen diesen beiden direkten Initialisierungen:
T x(a); // 1
T x{a}; // 2
und ähnlich zwischen diesen beiden Kopierinitialisierungen:
T x = a; // 1
T x = {a}; // 2
Nämlich die mit {..}
Verwenden Sie die Listeninitialisierung. Das {..}
heißt ein geklammerte Init-Liste.
Also, wenn Sie vergleichen T x = a;
zu T x {a};
es gibt zwei Unterschiede: Copy- vs. Direct-Initialisierung und “Non-List-” vs. List-Initialisierung. Wie bereits von anderen und im obigen Zitat erwähnt, für Nicht-Klassen-Typen T
, gibt es keinen Unterschied zwischen Copy- und Direct-Init. Es gibt jedoch einen Unterschied zwischen list-init und no list-init. Das heißt, wir könnten genauso gut vergleichen
int x (a);
int x {a};
Die Listeninitialisierung verbietet in diesem Fall einschränkende Konvertierungen. Eingrenzende Konvertierungen sind in definiert [dcl.init.list]/7 als:
Eine einschränkende Konvertierung ist eine implizite Konvertierung
-
von einem Gleitkommatyp zu einem ganzzahligen Typ oder
-
aus long double
zu double
oder float
oder von double
zu float
außer wenn die Quelle ein konstanter Ausdruck ist und der tatsächliche Wert nach der Konvertierung innerhalb des darstellbaren Wertebereichs liegt (auch wenn er nicht genau dargestellt werden kann), oder
-
von einem Integertyp oder Aufzählungstyp ohne Bereichsbegrenzung zu einem Gleitkommatyp, außer wenn die Quelle ein konstanter Ausdruck ist und der tatsächliche Wert nach der Konvertierung in den Zieltyp passt und den ursprünglichen Wert ergibt, wenn er wieder in den ursprünglichen Typ konvertiert wird, oder
-
von einem ganzzahligen Typ oder einem Aufzählungstyp ohne Bereichseinschränkung zu einem ganzzahligen Typ, der nicht alle Werte des ursprünglichen Typs darstellen kann, es sei denn, die Quelle ist ein konstanter Ausdruck, dessen Wert nach ganzzahligen Heraufstufungen in den Zieltyp passt.
Während für int
die vorhandenen Antworten vollständig sind, I schmerzlich herausgefunden, dass es in einigen Fällen andere Unterschiede zwischen den gibt ()
und {}
Initialisierungen.
Das Stichwort ist das {}
ist eine Initialisierungsliste.
Einer dieser Fälle ist die std::string
Initialisierung mit count
Kopien von A char
:
std::string stars(5, '*')
wird initialisiert stars
wie *****
aber
std::string stars{5, '*'}
wird gelesen als std::string stars(char(5), '*')
und initialisiere Stern als *
(mit vorangestelltem verstecktem Zeichen).
Die erste ist die Kopierinitialisierung, während die zweite die Listeninitialisierung ist.
Normalerweise wird die Kopierinitialisierung jedoch weniger verwendet. Denn wenn Sie dies tun, indem Sie Objekte benutzerdefinierter Typen übergeben, verursacht dies nur eine Bitkopie und führt daher möglicherweise nicht zu den beabsichtigten Ergebnissen, wenn die benutzerdefinierte Klasse Zeiger verwendet.
en.cppreference.com/w/cpp/language/initialization
– Chris
15. Januar 2014 um 23:08 Uhr
Zum
int
Der einzige Unterschied besteht insbesondere darin, dass{}
verbietet eine einschränkende Konvertierung, z. B. von einem Literal, das zu groß ist, um in ein zu passenint
. Bei Klassentypen kann es kompliziert werden, je nachdem, wie detailliert Sie die Unterschiede kennen möchten.– dyp
15. Januar 2014 um 23:09 Uhr