2013-01-21 9 views
5

Es scheint, dass die "für jeden" Stil der Syntax in C++ 11 Array-Iteration ohne Kenntnis der tatsächlichen Größe des Arrays (Anzahl der Elemente) ermöglicht. Ich nehme an, da dies Teil des neuen Standards ist, ist dies absolut sicher, sogar für C-Arrays. Typischerweise müssen Sie separat auch die Größe eines C-Array kennen, bevor es zu manipulieren, aber ich will Überprüfung von jemand mit dieser neuen C++ Technik erfahren, dass es genau funktioniert, wie man es erwarten würde:bereichsbasierte for-Schleifen in C++

extern float bunch[100]; 

for (float &f : bunch) { 
    f += someNumber; 
} 

Gibt es etwas, ich sollte über nicht offensichtliche Nebenwirkungen oder Nachteile dieser Technik wissen? Es zeigt nicht viel in Code, den ich sehe, wahrscheinlich weil der meiste Code geschrieben wurde, bevor dies im Standard war. Möchten Sie sicherstellen, dass seine seltene Verwendung nicht aus einem anderen Grund nicht bekannt ist.

+10

Sie können immer die Größe eines Arrays wissen (https://gist.github.com/3959946#file-arrays-h-L33). Wenn Sie das in Zeiger konvertieren, hören Sie auf, die Größe zu kennen. –

+1

@ R.MartinhoFernandes: Nice gist! –

+2

Im Allgemeinen werden Sie ein viel glücklicheres C++ Leben durch den Verzicht auf einfache Arrays und das Bewegen zu Standard-Bibliotheken-Containern führen. –

Antwort

4

Diese Verwendung ist nicht merkwürdig oder unsicher. Die Größe des Arrays ist zur Kompilierungszeit bekannt, sodass es in der Schleife verwendet werden kann. Dies ist ein Beispiel für eine Template-Funktion, die Sie die Länge eines Arrays, um herauszufinden erlaubt:

template< class T, std::size_t N > 
std::size_t length(const T (&)[N]) 
{ 
    return N; 
} 

Foo f[5]; 
std::cout << length(f) << "\n"; 

Dies sollte deutlich machen, dass Sie diese Technik nicht verwenden können, oder einen Bereich auf Basis Schleifen, auf dynamische Größe C-Stil Arrays.

Natürlich, wenn Sie Bereich auf Basis Schleifen haben, dann sollten Sie auch std::array haben (wenn nicht, können Sie wahrscheinlich ti von std::tr1 oder Schub erhalten), so dass Sie den C-Stil-Array vollständig vermeiden können:

extern std::array<float, 100> bunch; 

for (auto &f : bunch) { 
    f += someNumber; 
} 
+0

Ah, vielleicht ist meine Verwirrung dann der Unterschied zwischen einem C-Array und 'std :: array' - der Bereich basiert ist gültig für den letzteren, aber nicht für den ehemaligen, oder? Da ich immer dachte und gelesen hatte, dass ein C-Array kein Wissen über seine eigene Größe (Länge) – johnbakers

+1

@SebbyJohanns nein liefert, ist es für beide gültig, solange das C-artige Array statisch groß ist. Die obige Template-Funktion zeigt Ihnen, dass Sie die Größe aus einem solchen Array zurückholen können. – juanchopanza

+0

mit anderen Worten funktioniert es auf einem Array auf dem Stapel, nicht auf dem Haufen, richtig? – johnbakers

2

Arrays können als Referenzen übergeben werden und ihre Art und Länge abgeleitet werden.

#include <iostream> 

template<typename T, size_t N> 
void fun(T const (&arr)[N]) 
{ 
    for (std::size_t i = 0; i < N; ++i) 
     std::cout << arr[i] << " "; 
} 

int main() 
{ 
    int x[] = { 1, 2, 3 }; // no need to set length here 
    fun(x); // 1 2 3, no need to specify type and length here 
} 
+1

Es ist mir unklar, diese Vorlage zu betrachten, wie die 'size_t' für' N' in die Funktion 'fun' Wie extrahiert man den Wert für 'N'? – johnbakers

+0

Während der Schablonenargumentableitung betrachtet der Compiler das Argument (x, das vom Typ int [3] ist) und den formalen Parameter (arr vom Typ T [N]) und ersetzt int für T und 3 für N ergibt eine exakte Zahl Spiel. – TemplateRex

+0

@SebbyJohanns Der Typ des Arrays fester Größe enthält die Größe. Dann verwenden Sie den Vorlagenparameterabzug, um es zu erhalten. – juanchopanza

4

Es ist vollkommen sicher, eine bereichsbasierte for-Schleife mit Arrays zu verwenden. Ich nehme an, Sie befürchten, dass Sie es versehentlich auf einem Zeiger verwenden könnten:

Mach dir keine Sorgen, aber. Der Compiler wird in diesem Fall einen Fehler erzeugen. In Fällen, in denen es nicht sicher ist, erhalten Sie trotzdem einen Kompilierungsfehler.

+0

Das wäre sowieso sein eigener dummer Fehler für die Verwendung von 'new []'. – Puppy

+0

@DeadMG Was ist los mit 'new float [100]'? – johnbakers

+1

@DeadMG: "Dumb" ist nicht dasselbe wie "Unknowing". –

Verwandte Themen