C ++ 11 in gcc 4.8.1: list-initialization für den Kopierkonstruktor funktioniert nicht

8

Ich ermutige mit diesem Problem: Wenn ich

habe %Vor%

gcc gibt:

  

moves.cc: In der Funktion 'int main ()':   moves.cc:15:7: Fehler: zu viele Initialisierer für 'A'     A b {a};

Aber wenn ich A b (a) anstelle von A b {a} verwende, wird alles korrekt kompiliert. Und wenn ich default constructor deklariere, kompiliert es auch. Warum funktioniert es so?

    
user2834162 01.10.2013, 09:19
quelle

3 Antworten

14
___ answer19112572 ___

Wenn Sie Ihre eigenen -Konstruktoren nicht definieren wird A b(a) als ein Aggregat (dh plain-old-data ) Speichertyp betrachtet.

Beim Umgang mit einem Aggregat berücksichtigt list-initialization keine implizit deklarierten Konstruktoren, sondern versucht stattdessen, die Mitglieder Ihres Objekts direkt zu initialisieren.

Im Falle von A b{a} , wobei %code% ein Aggregat ist, versucht der Compiler das erste Element in %code% mit dem Wert von %code% zu initialisieren; Das wird natürlich fehlschlagen, da %code% keine Mitglieder enthält.

Was sagt der Standard?

  

%code%

  

1) Ein Aggregat ist ein Array oder eine Klasse (Abschnitt 9), das vom Benutzer nicht bereitgestellt wird   Konstruktoren (12.1) , keine Klammer-oder-Gleich-Initialisierung für nicht-statische   Datenmitglieder (9.2), keine privaten oder geschützten nicht-statischen Datenmitglieder   (Abschnitt 11), keine Basisklassen (Abschnitt 10) und keine virtuellen Funktionen   (10.3).

  

2) Wenn ein Aggregat von einer Initialisierungsliste initialisiert wird, wie z   In 8.5.4 sind die Elemente des Initialisierers als   Initialisierer für die Mitglieder des Aggregats , in steigendem Index   oder Mitglied bestellen. Jedes Mitglied wird von der Kopie initialisiert   entsprechende Initialisierungsklausel. Wenn die Initialisierungsklausel ein   Ausdruck und eine verengende Konvertierung (8.5.4) ist erforderlich, um zu konvertieren   der Ausdruck, das Programm ist schlecht geformt.

    
___ qstnhdr ___ C ++ 11 in gcc 4.8.1: list-initialization für den Kopierkonstruktor funktioniert nicht ___ tag123c ___ C ++ ist eine universelle Programmiersprache. Es wurde ursprünglich als Erweiterung von C entworfen und behält eine ähnliche Syntax, ist aber jetzt eine komplett andere Sprache. Verwenden Sie dieses Tag für Fragen zu Code, der mit einem C ++ - Compiler kompiliert werden soll. ___ tag123c11 ___ C ++ 11 ist eine 2011 verabschiedete Version des C ++ - Sprachstandards. Sie hat viele Änderungen und Ergänzungen der Kernsprache sowie der verbesserten und erweiterten C ++ - Standardbibliothek vorgenommen. ___ answer19116144 ___

GCC folgt dem Standard, aber das ist ein bekannter Defekt, siehe Kern Ausgabe 1467 und wird wahrscheinlich bald behoben werden.

    
___ tag123gcc ___ GCC ist die GNU Compiler-Sammlung. Es ist der De-facto-Standard-C-Compiler unter Linux und unterstützt auch viele andere Sprachen und Plattformen. ___ tag123uniforminitialization ___ Ein C ++ 11-Feature, mit dem geschweifte Klammern verwendet werden können, um einen beliebigen Typ von Variablen in einem beliebigen Kontext zu initialisieren ___ qstntxt ___

Ich ermutige mit diesem Problem: Wenn ich

habe %Vor%

gcc gibt:

  

moves.cc: In der Funktion 'int main ()':   moves.cc:15:7: Fehler: zu viele Initialisierer für 'A'     A b {a};

Aber wenn ich A b (a) anstelle von A b {a} verwende, wird alles korrekt kompiliert. Und wenn ich default constructor deklariere, kompiliert es auch. Warum funktioniert es so?

    
___ antwort19112526 ___

Die Klasse ist ein Aggregat, also führt die list-Initialisierung eine Aggregat-Initialisierung durch und berücksichtigt die implizit deklarierten Konstruktoren nicht.

Da keine Datenelemente vorhanden sind, kann nur eine leere Liste ein gültiger Aggregatinitialisierer sein.

  

Aber wenn ich %code% anstelle von %code% verwende, kompiliere alles korrekt.

Bei der direkten Initialisierung wird der implizite Konstruktor verwendet, anstatt die Aggregat-Initialisierung zu versuchen.

  

Und wenn ich default constructor deklariere, kompiliert es auch.

Durch die Deklaration eines Konstruktors ist die Klasse kein Aggregat mehr und kann nur mit einem Konstruktor initialisiert werden.

    
___
Mike Seymour 01.10.2013 09:25
quelle
9

Wenn Sie Ihre eigenen -Konstruktoren nicht definieren wird class A als ein Aggregat (dh plain-old-data ) Speichertyp betrachtet.

Beim Umgang mit einem Aggregat berücksichtigt list-initialization keine implizit deklarierten Konstruktoren, sondern versucht stattdessen, die Mitglieder Ihres Objekts direkt zu initialisieren.

Im Falle von A b { a } , wobei A ein Aggregat ist, versucht der Compiler das erste Element in A mit dem Wert von a zu initialisieren; Das wird natürlich fehlschlagen, da A keine Mitglieder enthält.

Was sagt der Standard?

  

[8.5.1 Aggregates]

  

1) Ein Aggregat ist ein Array oder eine Klasse (Abschnitt 9), das vom Benutzer nicht bereitgestellt wird   Konstruktoren (12.1) , keine Klammer-oder-Gleich-Initialisierung für nicht-statische   Datenmitglieder (9.2), keine privaten oder geschützten nicht-statischen Datenmitglieder   (Abschnitt 11), keine Basisklassen (Abschnitt 10) und keine virtuellen Funktionen   (10.3).

  

2) Wenn ein Aggregat von einer Initialisierungsliste initialisiert wird, wie z   In 8.5.4 sind die Elemente des Initialisierers als   Initialisierer für die Mitglieder des Aggregats , in steigendem Index   oder Mitglied bestellen. Jedes Mitglied wird von der Kopie initialisiert   entsprechende Initialisierungsklausel. Wenn die Initialisierungsklausel ein   Ausdruck und eine verengende Konvertierung (8.5.4) ist erforderlich, um zu konvertieren   der Ausdruck, das Programm ist schlecht geformt.

    
Filip Roséen - refp 01.10.2013 09:27
quelle
1

GCC folgt dem Standard, aber das ist ein bekannter Defekt, siehe Kern Ausgabe 1467 und wird wahrscheinlich bald behoben werden.

    
Jonathan Wakely 01.10.2013 12:26
quelle