C ++ 11: Std :: Array-Initialisierung korrigieren?


69

Wenn ich ein std :: -Array wie folgt initialisiere, warnt mich der Compiler vor fehlenden geschweiften Klammern

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

Dies behebt das Problem:

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

Dies ist die Warnmeldung:

missing braces around initializer for 'std::array<int, 4u>::value_type [4] {aka int [4]}' [-Wmissing-braces]

Ist dies nur ein Fehler in meiner Version von gcc oder wird es absichtlich gemacht? Wenn ja warum?


3
std::arrayist ein Aggregat. Ich denke jedoch, dass sie es in Zukunft mit einem Set zum Laufen bringen könnten.
Chris

@chris Was genau meinst du damit?
Byzanz

4
Nun, wissen Sie, wie Sie es mit haben struct S {int i; int j;};und initialisieren können S s = {5, 6};? Das ist eine aggregierte Initialisierung. std::arrayenthält ein eingebautes Array, das über eine Initialisierungsliste initialisiert werden kann. Dies ist die innere Menge. Der äußere Satz dient zur aggregierten Initialisierung.
Chris

@chris Also ist in meinem Fall "{1, 2, 3, 4}" nur ein std :: initializer_list-Objekt, das selbst in die eigentlichen Initialisierungsklammern gesetzt werden muss?
Byzanz

Nun, ich bin mir nicht ganz sicher, wie integrierte Array-Initialisierungslisten nach der Einführung dieses Typs behandelt werden, aber das ist der Kern davon, ja. Einer ist für die Klasse und der andere für das Array innerhalb der Klasse.
Chris

Antworten:


49

Dies ist die bloße Implementierung von std::array:

template<typename T, std::size_t N>
struct array {
    T __array_impl[N];
};

Es ist eine aggregierte Struktur, deren einziges Datenelement ein traditionelles Array ist, sodass das innere {}zum Initialisieren des inneren Arrays verwendet wird.

Die Klammerelision ist in bestimmten Fällen mit aggregierter Initialisierung zulässig (wird jedoch normalerweise nicht empfohlen). Daher kann in diesem Fall nur eine Klammer verwendet werden. Siehe hier: C ++ - Vektor von Arrays


Alle Versionen des Standards ermöglichen die Klammerentfernung.
Cubbi

Huh, dumme GCC-Warnungen>.> Mir war nicht bewusst, dass dies bereits der Fall war.
Chris

Ich hatte das gleiche Problem (bis jetzt 2016), aber ich habe es mit der folgenden Syntax behoben: 'std :: array <int, 4> a [] = {1,2,3,4};' Also habe ich eckige Klammern anstelle von verschachtelten geschweiften Klammern hinzugefügt. Vielleicht weiß jemand, warum diese Variante bei mir funktioniert hat?
Sam

5
@ Sam Das hat eine andere Bedeutung. Die von Ihnen veröffentlichte Syntax erstellt ein Array von std :: arrays (ein zweidimensionales Array) anstelle eines einzelnen Arrays (eindimensional).
Pubby

36

Nach cppreference . Doppelklammern sind nur erforderlich, wenn sie =weggelassen werden.

// construction uses aggregate initialization
std::array<int, 3> a1{ {1,2,3} };    // double-braces required
std::array<int, 3> a2 = {1, 2, 3}; // except after =
std::array<std::string, 2> a3 = { {std::string("a"), "b"} };

4
@cyberpunk_ nur, wenn Ihr Compiler DR # 1270 implementiert hat, wodurch diese Einschränkung aufgehoben wird .
Cubbi

@Chubbi Aber warum gibt es mir dann eine Warnung für "std :: array <int, 4> a = {1, 2, 3, 4}"?
Byzanz

@cyberpunk_ Es ist nur eine falsche Warnung.
Cubbi

4
@cyberpunk_ Sie können es trivial mit den zusätzlichen Klammern befriedigen. Es ist nicht die einzige nervige Warnung, die GCC (jemals gesehen suggest parentheses around ‘&&’ within ‘||’?)
Hat

2
Die Warnung bedeutet, dass der Compiler-Writer der Meinung ist, dass Sie möglicherweise nicht klug genug sind, um diese Sprachfunktion korrekt zu verwenden.
Pete Becker

6

In C ++ 11 vor dem CWG 1270 sind doppelte Klammern erforderlich (in C ++ 11 nach der Überarbeitung und in C ++ 14 und darüber hinaus nicht erforderlich):

// construction uses aggregate initialization
std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 prior to the CWG 1270 revision
                                    // (not needed in C++11 after the revision and in C++14 and beyond)
std::array<int, 3> a2 = {1, 2, 3};  // never required after =

std :: array referenz


2

C ++ 17 std::array Klassenvorlagenargumentabzug (CTAD)

Diese neue C ++ 17-Funktion wird von der Standardbibliothek verwendet und ermöglicht es uns nun, auch die Vorlagentypen wegzulassen, damit Folgendes funktioniert:

main.cpp

#include <array>

int main() {
    std::array a{1, 2, 3};
}

Anstatt von std::array<int, 3> a{1, 2, 3};

Getestet mit:

g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp

Wenn wir -std=c++14stattdessen zum Beispiel setzen, kann es nicht kompiliert werden mit:

error: missing template arguments before ‘a’

Siehe auch: Größe von std :: array ableiten?

Getestet unter Ubuntu 18.04, GCC 7.5.0.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.