Namensräume
Varianten
Aktionen

Array-Deklaration

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Deklariert ein Objekt vom Array-Typ.

Inhalt

[bearbeiten] Syntax

Eine Array-Deklaration ist jede einfache Deklaration, deren Deklarator die Form hat

noptr-declarator [expr (optional)] attr (optional)
noptr-declarator - ein beliebiger gültiger Deklarator, aber wenn er mit *, & oder && beginnt, muss er von Klammern umschlossen sein (andernfalls wird der gesamte Deklarator als Pointer-Deklarator oder Referenz-Deklarator behandelt).
expr - ein ganzzahliger konstanter Ausdruck(bis C++14)ein konvertierter konstanter Ausdruck vom Typ std::size_t(seit C++14), der zu einem Wert größer als Null ausgewertet wird
attr - (seit C++11) Liste von Attributen

Eine Deklaration der Form T a[N]; deklariert a als Array- Objekt, das aus N zusammenhängend alloziierten Objekten vom Typ T besteht. Die Elemente eines Arrays sind nummeriert von 0 bis N - 1 und können mit dem Indexoperator [] angesprochen werden, z. B. a[0] bis a[N - 1].

Arrays können aus jedem fundamentalen Typ (außer void), Pointern, Pointern auf Member, Klassen, Enumerationen oder aus anderen Arrays bekannter Größe (in diesem Fall wird das Array als mehrdimensional bezeichnet) konstruiert werden. Mit anderen Worten, nur Objekttypen außer Array-Typen unbekannter Größe können Elementtypen von Array-Typen sein. Array-Typen mit unvollständigem Elementtyp sind ebenfalls unvollständige Typen.

Der möglicherweise eingeschränkte(seit C++20) auto-Spezifizierer kann als Array-Elementtyp in der Deklaration eines Pointers oder einer Referenz auf ein Array verwendet werden, was den Elementtyp aus dem Initialisierer ableitet oder dem Funktionsargument(seit C++14), z. B. ist auto (*p)[42] = &a; gültig, wenn a ein lvalue vom Typ int[42] ist.

(seit C++11)

Es gibt keine Arrays von Referenzen oder Arrays von Funktionen.

Die Anwendung von cv-Qualifizierern auf einen Array-Typ (über typedef oder Template-Typmanipulation) wendet die Qualifizierer auf den Elementtyp an, aber jeder Array-Typ, dessen Elemente cv-qualifiziert sind, wird als gleichermaßen cv-qualifiziert betrachtet.

// a and b have the same const-qualified type "array of 5 const char"
 
typedef const char CC;
CC a[5] = {};
 
typedef char CA[5];
const CA b = {};

Bei Verwendung mit new[]-Ausdruck kann die Größe eines Arrays null sein; ein solches Array hat keine Elemente.

int* p = new int[0]; // accessing p[0] or *p is undefined
delete[] p; // cleanup still required

[bearbeiten] Zuweisung

Objekte vom Array-Typ können nicht als Ganzes modifiziert werden: Obwohl sie lvalues sind (z. B. kann die Adresse eines Arrays genommen werden), können sie nicht auf der linken Seite eines Zuweisungsoperators erscheinen.

int a[3] = {1, 2, 3}, b[3] = {4, 5, 6};
int (*p)[3] = &a; // okay: address of a can be taken
a = b;            // error: a is an array
 
struct { int c[3]; } s1, s2 = {3, 4, 5};
s1 = s2; // okay: implicitly-defined copy assignment operator
         // can assign data members of array type

[bearbeiten] Array-zu-Pointer-Zerfall

Es gibt eine implizite Konvertierung von lvalues und rvalues vom Array-Typ zu rvalues vom Pointer-Typ: Sie konstruiert einen Pointer auf das erste Element eines Arrays. Diese Konvertierung wird verwendet, wenn Arrays in einem Kontext erscheinen, in dem Arrays nicht erwartet werden, aber Pointer schon.

#include <iostream>
#include <iterator>
#include <numeric>
 
void g(int (&a)[3])
{
    std::cout << a[0] << '\n';
}
 
void f(int* p)
{
    std::cout << *p << '\n';
}
 
int main()
{
    int a[3] = {1, 2, 3};
    int* p = a;
 
    std::cout << sizeof a << '\n'  // prints size of array
              << sizeof p << '\n'; // prints size of a pointer
 
    // where arrays are acceptable, but pointers aren't, only arrays may be used
    g(a); // okay: function takes an array by reference
//  g(p); // error
 
    for (int n : a)            // okay: arrays can be used in range-for loops
        std::cout << n << ' '; // prints elements of the array
//  for (int n : p)            // error
//      std::cout << n << ' ';
 
    std::iota(std::begin(a), std::end(a), 7); // okay: begin and end take arrays
//  std::iota(std::begin(p), std::end(p), 7); // error
 
    // where pointers are acceptable, but arrays aren't, both may be used:
    f(a); // okay: function takes a pointer
    f(p); // okay: function takes a pointer
 
    std::cout << *a << '\n' // prints the first element
              << *p << '\n' // same
              << *(a + 1) << ' ' << a[1] << '\n'  // prints the second element
              << *(p + 1) << ' ' << p[1] << '\n'; // same
}

[bearbeiten] Mehrdimensionale Arrays

Wenn der Elementtyp eines Arrays ein anderes Array ist, wird das Array als mehrdimensional bezeichnet.

// array of 2 arrays of 3 int each
int a[2][3] = {{1, 2, 3},  // can be viewed as a 2 × 3 matrix
               {4, 5, 6}}; // with row-major layout

Beachten Sie, dass bei Anwendung des Array-zu-Pointer-Zerfalls ein mehrdimensionales Array in einen Pointer auf sein erstes Element konvertiert wird (z. B. ein Pointer auf seine erste Zeile oder seine erste Ebene): Der Array-zu-Pointer-Zerfall wird nur einmal angewendet.

int a[2];            // array of 2 int
int* p1 = a;         // a decays to a pointer to the first element of a
 
int b[2][3];         // array of 2 arrays of 3 int
// int** p2 = b;     // error: b does not decay to int**
int (*p2)[3] = b;    // b decays to a pointer to the first 3-element row of b
 
int c[2][3][4];      // array of 2 arrays of 3 arrays of 4 int
// int*** p3 = c;    // error: c does not decay to int***
int (*p3)[3][4] = c; // c decays to a pointer to the first 3 × 4-element plane of c

[bearbeiten] Arrays unbekannter Größe

Wenn expr in der Deklaration eines Arrays weggelassen wird, ist der deklarierte Typ "Array unbekannter Größe von T", was eine Art unvollständiger Typ ist, außer wenn er in einer Deklaration mit einem Aggregatinitialisierer verwendet wird.

extern int x[];      // the type of x is "array of unknown bound of int"
int a[] = {1, 2, 3}; // the type of a is "array of 3 int"

Da Array-Elemente keine Arrays unbekannter Größe sein können, können mehrdimensionale Arrays in keiner Dimension außer der ersten eine unbekannte Größe haben.

extern int a[][2]; // okay: array of unknown bound of arrays of 2 int
extern int b[2][]; // error: array has incomplete element type

Wenn eine vorherige Deklaration der Entität im selben Gültigkeitsbereich vorhanden ist, in der die Größe angegeben wurde, wird eine weggelassene Array-Größe als gleich der in der früheren Deklaration angenommen, und ebenso für die Definition eines statischen Datenmembers einer Klasse.

extern int x[10];
struct S
{
    static int y[10];
};
 
int x[];               // OK: bound is 10
int S::y[];            // OK: bound is 10
 
void f()
{
    extern int x[];
    int i = sizeof(x); // error: incomplete object type
}

Referenzen und Pointer auf Arrays unbekannter Größe können gebildet werden, aber nicht(bis C++20)und können(seit C++20) von Arrays und Pointern auf Arrays bekannter Größe initialisiert oder zugewiesen werden. Beachten Sie, dass im C-Programmiersprachen-Standard Pointer auf Arrays unbekannter Größe mit Pointern auf Arrays bekannter Größe kompatibel sind und somit in beide Richtungen konvertierbar und zuweisbar sind.

extern int a1[];
 
int (&r1)[] = a1;  // okay
int (*p1)[] = &a1; // okay
int (*q)[2] = &a1; // error (but okay in C)
 
int a2[] = {1, 2, 3};
int (&r2)[] = a2;  // okay (since C++20)
int (*p2)[] = &a2; // okay (since C++20)

Pointer auf Arrays unbekannter Größe können nicht an Pointer-Arithmetik teilnehmen und können nicht links vom Indexoperator verwendet werden, können aber dereferenziert werden.

[bearbeiten] Array-Rvalues

Obwohl Arrays nicht per Wert von Funktionen zurückgegeben werden können und keine Ziele der meisten Cast-Ausdrücke sind, können Array- prvalues durch Verwendung eines Typalias gebildet werden, um ein Array-Temporäres mit einem funktionalen Cast mit geschweiften Klammern zu konstruieren.

Wie Klassen-prvalues konvertieren Array-prvalues durch temporäre Materialisierung zu xvalues, wenn sie ausgewertet werden.

(seit C++17)

Array- xvalues können direkt durch Zugriff auf ein Array-Mitglied eines Klassen-rvalues oder durch Verwendung von std::move oder eines anderen Casts oder Funktionsaufrufs, der eine rvalue-Referenz zurückgibt, gebildet werden.

#include <iostream>
#include <type_traits>
#include <utility>
 
void f(int (&&x)[2][3])
{
    std::cout << sizeof x << '\n';
}
 
struct X
{
    int i[2][3];
} x;
 
template<typename T>
using identity = T;
 
int main()
{
    std::cout << sizeof X().i << '\n';           // size of the array
    f(X().i);                                    // okay: binds to xvalue
//  f(x.i);                                      // error: cannot bind to lvalue
 
    int a[2][3];
    f(std::move(a));                             // okay: binds to xvalue
 
    using arr_t = int[2][3];
    f(arr_t{});                                  // okay: binds to prvalue
    f(identity<int[][3]>{{1, 2, 3}, {4, 5, 6}}); // okay: binds to prvalue
 
}

Ausgabe

24
24
24
24
24

[bearbeiten] Defect Reports

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 393 C++98 ein Pointer oder eine Referenz auf ein Array unbekannter
Größe konnte kein Funktionsparameter sein
erlaubt
CWG 619 C++98 wenn weggelassen, konnte die Größe eines Arrays
nicht aus einer vorherigen Deklaration abgeleitet werden
Ableitung erlaubt
CWG 2099 C++98 die Größe eines statischen Datenmembers eines Arrays konnte
nicht weggelassen werden, auch wenn ein Initialisierer bereitgestellt wurde
Weglassen erlaubt
CWG 2397 C++11 auto konnte nicht als Elementtyp verwendet werden erlaubt

[bearbeiten] Siehe auch

C-Dokumentation für Array-Deklaration