2012-11-13 3 views
9

Wenn ich so etwas tun:Wie kennt die C++ 11-basierte for-Schleife die Array-Größe?

int my_array[5] = {1, 2, 3, 4, 5}; 
for (int &x : my_array) { 
    x *= 2; 
} 

C++ 11 weiß offensichtlich, dass mein Array 5 Elemente nur hat. Wird diese Information irgendwo im my_array-Objekt gespeichert?

Wenn ja, gibt es einen guten Grund, warum es mir als Entwickler nicht zur Verfügung gestellt wird (oder ist es?!?!?)? Es scheint, dass viele der Probleme der Welt gelöst würden, wenn C++ - Entwickler immer die Grenzen der Arrays kennen würden, mit denen sie zu tun haben.

Antwort

11

Dies ist einfach etwas, das die Sprache benötigt, um zu arbeiten, und der Compiler muss implementieren. Offensichtlich ist der vollständige Typ von my_arrayint[5] (d. H. Die Größe ist Teil des Typs), so dass diese Information leicht verfügbar ist.

Entgegen der landläufigen Meinung gibt es keine Verwendung der freien std::begin()/std::end() Funktionen im Spiel, obwohl jene naiv scheint der Lage zu sein, den Trick zu tun (aber es gibt einen Haken ADL beteiligt, die diesen Ansatz brechen würde) .

+0

Ok. Gibt es also einen bestimmten Grund, warum eine my_array.size nicht existiert? – MrFox

+6

@suslik: Sicher, denn Arrays sind keine Klassen und können daher keine Mitgliedsfunktionen haben. Aber Sie können trivial eine "array_size" -Freiheitsfunktionsvorlage schreiben, die den gewünschten Wert erzeugt, oder Sie verwenden das einfach zu erstellende ['std :: excument'] (http://en.cppreference.com/w/cpp/types/extent). –

+0

Wie lebe ich mein Leben nicht so lange zu wissen ... Ich beschuldige std :: vector :). – MrFox

5

Nein, es ist nicht Teil des Objekts. Aber es ist Teil des Typs. Das ist, was die 5 in der Array-Deklaration ist. Allerdings wird dies nicht funktionieren:

void f(int arr[5]) { 
    for(int& x: arr) { 
     // whatever 
    } 
} 

, weil der Name des Arrays hier zerfällt in einen Zeiger auf das erste Element, das heißt, ist das Argument Erklärung int *arr Äquivalent, die keine Größeninformationen hat.

+3

Ich würde in diesem Fall nicht den Begriff "Zerfall" verwenden. Ich denke, dass dieser Begriff normalerweise spezifisch für die implizite Konvertierung ist, die für eine Array-Variable in vielen Ausdrücken durchgeführt wird. 'int a [5]; a + 1; // zerfall "Ich möchte mich stattdessen auf das beziehen, was hier mit dem Begriff" Anpassen "geschieht, denn das ist das Wort, das der Standard verwendet. 'void foo (int a [5]); // type 'adjustment': entspricht void foo (int * a) '. Und ich verwende gerne einen sarkastischen Ton, wenn ich das Wort sage. – bames53

+0

Das würde aber funktionieren. 'void f (int (& arr) [5]) {...}' – balki

+0

Als Referenz funktioniert die @ balki-Lösung nicht mit unsized-Array-Referenzen, z. '(& arr) [5]'. Es kann jedoch in der Regel dazu gebracht werden, für generische Arrays zu arbeiten, indem die Array-Größe als Template-Parameter verwendet wird: siehe https://stackoverflow.com/questions/26182907/range-based-for-loop-on-array-passed- to-non-main-function – andybuckley

6

Es ist verfügbar - Sie können begin und end auf Arrays in Standard-C++ definieren. Die Größe des Arrays ist im Typ codiert.

Die allgemeine Methode besteht darin, Verweise auf Arrays zu verwenden.

Hier ist ein Beispiel Größe Funktion:

template<typename T, size_t N> 
size_t array_size(T (& const)[N]) 
{ 
    return N; 
} 
+6

Dies wird auch als 'std :: excent' bezeichnet.Und 'std :: begin' und' std :: end' sind * bereits * für Arrays in der Standardbibliothek definiert. –

Verwandte Themen