In C ++ 11 können Sie eine bereichsbasierte Version verwenden for
, die wie die foreach
anderer Sprachen fungiert. Es funktioniert sogar mit einfachen C-Arrays:
int numbers[] = { 1, 2, 3, 4, 5 };
for (int& n : numbers) {
n *= 2;
}
Woher weiß es, wann es aufhören soll? Funktioniert es nur mit statischen Arrays, die im selben Bereich deklariert wurden, in dem sie for
verwendet werden? Wie würden Sie dies for
mit dynamischen Arrays verwenden?
for
. In dem Moment, in dem das Array in einen Zeiger zerfällt, gehen die Größeninformationen verloren.numbers
istsizeof(numbers)/sizeof(int)
, zum Beispiel.Antworten:
Es funktioniert für jeden Ausdruck, dessen Typ ein Array ist. Beispielsweise:
Für eine detailliertere Erklärung: Wenn der Typ des rechts übergebenen Ausdrucks
:
ein Array-Typ ist, iteriert die Schleife vonptr
bisptr + size
(ptr
zeigt auf das erste Element des Arrays,size
wobei es sich um die Elementanzahl des Arrays handelt).Dies steht im Gegensatz zu benutzerdefinierten Typen, die nachschlagen
begin
undend
als Mitglieder arbeiten, wenn Sie ein Klassenobjekt übergeben oder (wenn es keine so genannten Mitglieder gibt) Nichtmitgliedsfunktionen. Diese Funktionen ergeben die Start- und Enditeratoren (die direkt nach dem letzten Element bzw. dem Beginn der Sequenz zeigen).Diese Frage klärt, warum dieser Unterschied besteht.
quelle
begin
`end. It just happens that
std :: begin,`std::end
benutze die Mitgliedsfunktionen und werde verwendet, wenn keine bessere Übereinstimmung verfügbar ist.Ich denke, dass der wichtigste Teil dieser Frage ist, wie C ++ weiß, wie groß ein Array ist (zumindest wollte ich es wissen, als ich diese Frage fand).
C ++ kennt die Größe eines Arrays, da es Teil der Array-Definition ist - es ist der Typ der Variablen. Ein Compiler muss den Typ kennen.
Da C ++ 11
std::extent
verwendet werden kann, um die Größe eines Arrays zu erhalten:Dies ist natürlich nicht sehr sinnvoll, da Sie die Größe in der ersten Zeile explizit angeben müssen, die Sie dann in der zweiten Zeile erhalten. Sie können aber auch verwenden
decltype
und dann wird es interessanter:quelle
Gemäß dem neuesten C ++ - Arbeitsentwurf (n3376) entspricht der Bereich für Anweisungen dem folgenden:
Es weiß also, wie man eine reguläre
for
Schleife mit Iteratoren auf die gleiche Weise stoppt .Ich denke, Sie suchen möglicherweise nach etwas wie dem Folgenden, um die obige Syntax für Arrays zu verwenden, die nur aus einem Zeiger und einer Größe bestehen (dynamische Arrays):
Diese Klassenvorlage kann dann verwendet werden, um einen Bereich zu erstellen, über den Sie mithilfe des neuen Bereichs für die Syntax iterieren können . Ich verwende dies, um alle Animationsobjekte in einer Szene zu durchlaufen, die mit einer Bibliothek importiert werden, die nur einen Zeiger auf ein Array und eine Größe als separate Werte zurückgibt.
Diese Syntax ist meiner Meinung nach viel klarer als das, was Sie verwenden würden,
std::for_each
oder eine einfachefor
Schleife.quelle
Es weiß, wann es aufhören muss, weil es die Grenzen statischer Arrays kennt.
Ich bin mir nicht sicher, was Sie unter "dynamischen Arrays" verstehen. Wenn der Compiler nicht informell über statische Arrays iteriert, sucht er auf jeden Fall nach den Namen
begin
undend
im Bereich der Klasse des Objekts, über das Sie iterieren, oder schaut bereit fürbegin(range)
undend(range)
mit argumentabhängiger Suche und verwendet sie als Iteratoren.Weitere Informationen finden Sie im C ++ 11-Standard (oder im öffentlichen Entwurf davon) unter "6.5.4 Die bereichsbasierte
for
Anweisung", S. 145quelle
new[]
. In diesem Fall haben Sie nur einen Zeiger ohne Angabe der Größe, sodass der bereichsbasierte Benutzer nichtfor
damit arbeiten kann.Soll das lauten: " Sag mir, was ein Fernkampf macht (mit Arrays)? "
Ich antworte unter der Annahme, dass - Nehmen Sie das folgende Beispiel mit verschachtelten Arrays:
Textversion:
ia
ist ein Array von Arrays ("verschachteltes Array"), die[3]
Arrays enthalten , wobei jedes[4]
Werte enthält. Das obige Beispiel durchläuftia
seinen primären 'Bereich' ([3]
) und durchläuft daher die[3]
Zeiten. Jede Schleife erzeugt eine vonia
‚s[3]
Primärwerte aus dem ersten und endend mit dem letzten - Ein Array mit[4]
Werten.pl
gleich{1,2,3,4}
- Ein Arraypl
gleich{5,6,7,8}
- Ein Arraypl
gleich{9,10,11,12}
- Ein ArrayBevor wir den Prozess erklären, sind hier einige freundliche Erinnerungen an Arrays:
pl
muss eine Referenz sein, da wir keine Arrays kopieren könnenn
es sich um die betreffende Nummer handelt,ia[n]
ist dies dieselbe wie*(ia+n)
(Wir dereferenzieren die Adresse, dien
Einträge enthält forward) undia+n
ist dasselbe wie&ia[n]
(Wir erhalten die Adresse dieses Eintrags im Array).Folgendes ist los:
pl
als Referenz auf gesetztia[n]
, wobein
die aktuelle Schleifenzahl ab 0 gleichpl
ist. Ist alsoia[0]
in der ersten Runde, in der zweiten ist esia[1]
und so weiter. Der Wert wird per Iteration abgerufen.ia+n
kleiner als istend(ia)
.... und das war's auch schon.
Es ist wirklich nur eine vereinfachte Art, dies zu schreiben :
Wenn Ihr Array ist nicht verschachtelt, dann wird dieser Prozess etwas einfacher, dass eine Referenz nicht erforderlich, da der iterierten Wert kein Array ist , sondern ein ‚normaler‘ Wert:
Einige zusätzliche Informationen
Was wäre, wenn wir das
auto
Schlüsselwort beim Erstellen nicht verwenden wollten?pl
? Wie würde das aussehen?Im folgenden Beispiel
pl
bezieht sich auf einearray of four integers
. In jeder Schleifepl
wird der Wert angegebenia[n]
:Und ... so funktioniert es, mit zusätzlichen Informationen, um Verwirrung zu beseitigen. Es ist nur eine Kurzschleife,
for
die automatisch für Sie zählt, aber keine Möglichkeit bietet, die aktuelle Schleife abzurufen, ohne sie manuell auszuführen.quelle
Einige Beispielcodes, um den Unterschied zwischen Arrays auf Stack und Arrays auf Heap zu demonstrieren
quelle