Warum unterscheidet sich das C++-Verhalten initializer_list für std::vector und std::array?

Lesezeit: 3 Minuten

Warum unterscheidet sich das C Verhalten initializer list fur stdvector und stdarray
Sungmin

Code:

std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};

Warum brauche ich doppelte geschweifte Klammern für std::array?

  • Benötigen Sie eigentlich die zweite Zahnspange für std::arrayoder bekommst du nur eine Warnung? std::array<int,4> y{1,2,3,4}; funktioniert bei mir.

    – Namen53

    9. Juli 12 um 17:36 Uhr

  • @ bames53: GCC hat das falsch kompiliert.

    – Xeo

    9. Juli 12 um 17:39 Uhr

  • @Xeo: Es ist nicht “falsch”, ein schlecht geformtes Programm mit einer Warnung zu kompilieren.

    – Steve Jessop

    9. Juli 12 um 17:43 Uhr


  • @Steve: Das stimmt. Sagen wir nicht tragbar?

    – Xeo

    9. Juli 12 um 17:46 Uhr

  • @Xeo: ja, benutze ich -Werror sowieso für Code, den ich geschrieben habe, also schadet es meiner Portabilität nicht. Der Kilometerstand anderer kann variieren, wenn sie Leichtgewichte sind oder Header-Dateien enthalten müssen, die von Leichtgewichten geschrieben wurden 🙂

    – Steve Jessop

    9. Juli 12 um 17:47 Uhr


Warum unterscheidet sich das C Verhalten initializer list fur stdvector und stdarray
James McNellis

std::array<T, N> ist ein Aggregat: Es hat keine vom Benutzer deklarierten Konstruktoren, nicht einmal einen, der a nimmt std::initializer_list. Die Initialisierung mit geschweiften Klammern erfolgt mit Aggregat-Initialisierungeine Funktion von C++, die von C geerbt wurde.

Der “alte Stil” der Aggregatinitialisierung verwendet die =:

std::array<int, 4> y = { { 1, 2, 3, 4 } };

Bei diesem alten Stil der Aggregatinitialisierung können zusätzliche Klammern weggelassen werden, also ist dies äquivalent zu:

std::array<int, 4> y = { 1, 2, 3, 4 };

Diese zusätzlichen geschweiften Klammern dürfen jedoch nur in einer Erklärung des Formulars weggelassen werden T x = { a };” (C++11 §8.5.1/11), das heißt, wenn der alte Stil = wird genutzt . Diese Regel, die das Entfernen von geschweiften Klammern erlaubt, gilt nicht für die direkte Listeninitialisierung. Eine Fußnote hier lautet: “Klammern können bei anderen Verwendungen der Listeninitialisierung nicht entfernt werden.”

Zu dieser Einschränkung gibt es einen Mängelbericht: CWG-Defekt Nr. 1270. Wenn die vorgeschlagene Resolution angenommen wird, wird das Weglassen von Klammern für andere Formen der Listeninitialisierung zugelassen, und das Folgende wird wohlgeformt sein:

std::array<int, 4> y{ 1, 2, 3, 4 };

(Hutspitze an Ville Voutilainen für das Auffinden des Fehlerberichts.)

  • Es ist also ein Versagen des vorgestellten Abstraktionsmodells array?

    – Markieren Sie Lösegeld

    9. Juli 12 um 17:35 Uhr

  • @Mehrdad: Es ist Uniform. Was ist nicht einheitlich ist die Tatsache, dass Sie zwei völlig unterschiedliche Typen initialisieren.

    – Nicol Bolas

    9. Juli 12 um 17:35 Uhr

  • @NicolBolas: Ich dachte, der Sinn der Einheitlichkeit bestehe darin, dieselbe Initialisierungssyntax für verschiedene Typen zu verwenden? (Ja, ich verstehe, was passiert … Ich sage nur, dass es für den Benutzer nicht “einheitlich” ist, unabhängig davon, ob es eine Erklärung dafür gibt.)

    – Benutzer541686

    9. Juli 12 um 17:36 Uhr


  • @MarkRansom: Nun, es ist eher eine Eigenart der Sprache, weil std::array<int> y = {1,2,3,4}; arbeitet mit einem Warnung von Klang vorschlagen geschweiften Klammern anstelle eines schwerwiegenden Fehlers, dass es nicht erlaubt ist, “geschweifte Klammern um die Initialisierung des Unterobjekts wegzulassen, wenn die direkte Listeninitialisierung verwendet wird”.

    – Xeo

    9. Juli 12 um 17:38 Uhr


  • @Xeo: Eigentlich ist das Entfernen von Klammern bei der Aggregatinitialisierung zulässig, aber (anscheinend) nicht, wenn die direkte Listeninitialisierungssyntax verwendet wird.

    – James McNellis

    9. Juli 12 um 18:01 Uhr

Denn std::vector bietet einen Konstruktor, der a aufnimmt std::initializer_list<T>während std::array hat keine Konstruktoren und die {1, 2, 3, 4} Die geklammerte Initialisierungsliste wird tatsächlich nicht als a interpretiert std::initializer_listaber aggregierte Initialisierung für das innere Array im C-Stil von std::array (daher kommt der zweite Satz geschweifter Klammern: One for std::arrayeine für das innere Member-Array im C-Stil).

.

821150cookie-checkWarum unterscheidet sich das C++-Verhalten initializer_list für std::vector und std::array?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy