Listeninitialisierungen in C++ (Listeninitialisierungen in C++), Lektion, Seite 721380
https://www.purl.org/stefan_ram/pub/listeninitialisierungen_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Initialisierungen mit geschweiften Klammern in C++ 

Einige in dieser Lektion verwendete Begriffe

Einengung Eine Einengung liegt vor, wenn ein Ausdruck in einem Typ gewandelt werden soll, aus dem keine eindeutige Rückwandlung in den ursprünglichen Typ möglich ist. (Falls der Wert des Ausdrucks beim Übersetzen bekannt ist, so reicht es schon aus, wenn dieser spezielle Wert eindeutig zurückgewandelt werden kann, damit es sich nicht um eine Einengung handelt.)

Auflösung Bei der Auflösung eines mehrdeutigen sprachlichen Ausdrucks wird versucht, dessen genaue Bedeutung in einem bestimmten Zusammenhang zu ermitteln.

Verb Ein Funktionsname, der ein Bezeichner ist, also keine Doppelpunkte enthält.

Überladungsauflösung Bei der Überladungsauflösung wird ermittelt, welche von mehreren Funktionen, die ein Verb überladen, am besten zu einem Aufruf dieses Verbs paßt.

Argumentliste Die Liste der Argumente bei einem Funktionsaufruf.

Die Schreibweise mit geschweiften Klammern

Wir haben die Schreibweise mit geschweiften Klammern bereits als Direktinitialisierung  kennengelernt und verwendet. Bei fundamentalen Typen (wie int oder double) gibt es keinen Unterschied zur Direktinitialisierung mit runden Klammern, abgesehen davon, daß keine Einengung erlaubt ist.

Das folgende Beispiel zeigt, daß in den geschweiften Klammern auch eine kommagetrennte Liste mehrerer Ausdrücke  stehen kann und daß die geschweiften Klammern auch zur Initialisierung von Objekten mit benutzerdefiniertem Typ verwendet werden können. Die kommagetrennte Liste in den geschweiften Klammern wird in der Grammatik »initializer-list« genannt, ihre kommagetrennten Einträge sind die »initializer-clause«. Auch hier ist für die einzelnen Einträge der Liste keine einengende Umwandlung in den erwarteten Typ gestattet.

main.cpp

#include <initializer_list>
#include <iostream>
#include <ostream>
#include <cerrno> /* ::std::error_code, ::std::generic_category */

int main()
{ ::std::error_code const code{ 2, ::std::generic_category() };
::std::cout << code << '\n'; }

::std::cout
generic:2

Der Teil »{ 2, ::std::generic_category() }« ist oben kein  Ausdruck. Er könnte zwar an einer anderen Stelle auch einmal als Ausdruck vorkommen, er ist oben aber eine braced-init-list  (Initialisierungsliste). Seine Einträge sind das Numerale »2« und der Funktionsaufruf  »::std::generic_category()«.

Es handelt sich um eine Direkt-Initialisierung mit einer Initialisierungsliste.

Die genaue Bedeutung der verschiedenen Arten der Initialisierung hängt vom Typ des initialisierten Objekts ab, insbesondere von den definierten Konstruktoren.

Bei solch einer direkten Listeninitialisierung wird im allgemeinen ein Konstruktor aufgerufen, der zu den Ausdrücken in der Initialisierungsliste paßt.

Zu der Objektinitialisierung in dem obigen Programmbeispiel paßt der zweite Konstruktor aus der folgenden Liste an besten.

Dokumentation der Konstruktoren der Klasse »::std::error_code« nach C++ 2015, 19.5.2.2 (vereinfacht)
()
Erzeugt ein Objekt dieser Klasse mit der Kategorie »system« und dem Wert »0«.
( int val, error_category const & cat )
Erzeugt ein Objekt dieser Klasse mit der Kategorie »cat« und dem Wert »val«.

Das folgende Zitat gibt an, daß eine Initialisierung der Form wie in dem obigen Programmbeispiel eine Direkt-Initialisierung ist.

In dem folgenden Zitat kann »a« auch für eine Liste von Ausdrücken stehen!

C++ 2015 8.5p16 *
The initialization that occurs in the forms

T x( a );

T x{ a };

is called direct-initialization.

Das folgende Zitat besagt, daß eine Initialisierung der Form wie in dem obigen Programmbeispiel eine Listen-Initialisierung ist. (Sie ist also sowohl eine Direkt-Initialisierung als auch eine Listen-Initialisierung.)

C++ 2015 8.5p17.1 *
If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized.

Das folgende Zitat besagt, daß verengenden Umformungen bei einer Direkt-Listen-Initialisierung nicht gestattet sind.

C++ 2015 8.5.4p3.4 *
If a narrowing conversion (see below) is required to convert any of the arguments, the program is ill-formed.

Das folgende Zitat besagt, daß der passende Konstruktor vermittels einer Überladungsauflösung gesucht wird, wobei die Einträge der Initialisierungsliste die Einträge der Argumentliste bilden. Das heißt, daß die Auflösung wie bei einem Aufruf mit der Argumentliste »2, ::std::generic_category()« erfolgt.

C++ 2015 13.3.1.7p1 *
overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

Zur Syntax von Initialisierungslisten

Hier geben wir die für den Block »{ ::std::error_code const code{ 2, ::std::generic_category() }; }« relevanten Teile der Syntax von C++  an.

Syntax C++ 2015 (vereinfacht) *
compound-statement 〉 ::=
'{' [〈statement-seq 〉] '}'.
statement-seq 〉 ::=
statement 〉 |
statement-seq 〉 〈statement 〉.
statement 〉 ::=
declaration-statement 〉.
declaration-statement 〉 ::=
block-declaration 〉.
block-declaration 〉 ::=
simple-declaration 〉.
simple-declaration 〉 ::=
[〈decl-specifier-seq 〉] [〈init-declarator-list 〉] ';'.
decl-specifier-seq 〉 ::=
decl-specifier 〉 |
[〈
decl-specifier 〉] 〈decl-specifier-seq 〉.
decl-specifier 〉 ::=
type-specifier 〉.
type-specifier 〉 ::=
simple-type-specifier 〉 |
cv-qualifier 〉.
simple-type-specifier 〉 ::=
[〈nested-name-specifier 〉] 〈type-name 〉.
type-name 〉 ::=
class-name 〉.
class-name 〉 ::=
identifier 〉.
nested-name-specifier 〉 ::=
'::' |
type-name 〉 '::' |
namespace-name 〉 '::' |
nested-name-specifier 〉 〈 identifier 〉 '::'.
cv-qualifier 〉 ::=
'const' |
'
volatile'.
init-declarator-list 〉 ::=
init-declarator-list 〉 ',' 〈init-declarator 〉 |
init-declarator 〉.
init-declarator 〉 ::=
declarator 〉 [〈initializer 〉].
declarator 〉 ::=
ptr-declarator 〉.
ptr-declarator 〉 ::=
noptr-declarator 〉.
noptr-declarator 〉 ::=
declarator-id 〉.
declarator-id 〉 ::=
id-expression 〉.
id-expression 〉 ::=
unqualified-id 〉.
unqualified-id 〉 ::=
identifier 〉.
initializer 〉 ::=
brace-or-equal-initializer 〉 |
'
(' 〈expression-list 〉 ')'.
brace-or-equal-initializer 〉 ::=
'=' 〈initializer-clause 〉 |
braced-init-list 〉.
braced-init-list 〉 ::=
'{' 〈initializer-list 〉 [','] '}' |
'
{' '}'.
initializer-list 〉 ::=
initializer-clause 〉 |
initializer-list 〉 ',' 〈initializer-clause 〉.
initializer-clause 〉 ::=
assignment-expression 〉 |
braced-init-list 〉.

Die folgende Analyse zeigt einige syntaktische Kategorien einiger Teile des Blocks »{ ::std::error_code const code{ 2, ::std::generic_category() }; }«.

Wir greifen heraus: Die ganze simple-declaration »::std::error_code const code{ 2, ::std::generic_category() }« zerfällt in die decl-specifier-seq  »::std::error_code const«, den identifier  »code« und den initializer  »{ 2, ::std::generic_category() }«.

Jener initializer  besteht seinerseits wiederum aus zwei kommagetrennten initializer-clause s, welche beide jeweils assignment-expression  sind.

Analyse *

{ ::std::error_code const code{ 2, ::std::generic_category() }; }

| ||| | || | | | | || | ||| | || | | || |
| ||| | || | | | | || | C '3' |'----- 3 ------' | || |
| ||| | || | | | | || | | || | | || |
| ||| | || | | | | || | '- C -''----- 0 ------' | || |
| ||| | || | | | | || | | | | || |
| ||| | || | | | | || | '--- qualified-id ----' | || |
| ||| | || | | | | || | | | | || |
| ||| | || | | | | || | '--- id-expression ---' | || |
| ||| | || | | | | || | | | | || |
| ||| | || | | | | || | '-primary-expression--' | || |
| ||| | || | | | | || | | | | || |
| ||| | || | | | | || 1 '-postfix-expression--' | || | 0 = unqualified-id
| ||| | || | | | | || | | | || | 1 = literal
| ||| | || | | | '3-'| 2 '--postfix-expression --' || | 2 = conditional-expression
| ||| | || | | | | || | | | || | 3 = identifier
| ||| | || | | | '5-'| 4 ' assignment-expression ' || | 4 = assignment-expression
| ||| | || | | | | || | | | || | 5 = unqualified-id
| ||| | |'-- 3 ---' | | '7-'| 6 '- initializer-clause --' || | 6 = initializer-clause
| C '3' || | | | | || | | || | 7 = id-expression
| '-9-' |'-- 8 ---' | | |A-'| '---- initializer-list ----' || | 8 = class-name
| | || | | | | || || | 9 = namespace-name
| '- C -''-- B ---' | | 'D-''------ braced-init-list ------'| | A = declarator-id
| | | | | | || || | B = type-name
| '------ F ------' '-E-' 'G-''- brace-or-equal-initializer -'| | C = nested-name-specifier
| | | | | | || || | D = noptr-declarator
| '------ J ------' '-J-' 'I-''-------- initializer ---------'| | E = cv-qualifier
| | | | | | || | F = simple-type-specifier
| '------ K ------' '-K-' '-------- init-declarator ---------'| | G = ptr-declarator
| | | | || | I = declarator
| '--------- L ---------' '------ init-declarator-list ------'| | J = type-specifier
| | | | K = declaration-specifier
| '------------------- simple-declaration --------------------' | L = decl-specifier-seq
| | | |
| '-------------------- block-declaration --------------------' |
| | | |
| '------------------ declaration-statement ------------------' |
| | | |
| '------------------------ statement ------------------------' |
| | | |
| '---------------------- statement-seq ----------------------' |
| |
'--------------------- compound statement ----------------------'

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram721380 stefan_ram:721380 Listeninitialisierungen in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd721380, slrprddef721380, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/listeninitialisierungen_c++