2016-03-27 20 views
-1

Vor wenigen Tagen sah ich Code wie folgt:Zeiger als C++ Iterator

#include <iostream> 

void test(const int *x, int max){ 
    for(auto it = x; it < x + max; ++it) 
     std::cout << *it << std::endl; 
} 

int main(){ 
    constexpr int MAX = 5; 

    constexpr int x[MAX] = { 1,2,4,5,7 }; 

    test(x, MAX); 
} 

Neben Anwendungen von auto und constexpr, der Code funktioniert OK in C++11, C++ und sogar in C.

Es gibt jedoch etwas, das mich abgehört - der Code Zugriff auf das Element nach dem letzten Element z. - x[5]. Ich glaube in einigen Fällen könnte dies Adressverletzung sein, zum Beispiel wenn Sie mmap() etwas Speicher und versuchen, Speicher nach was Sie mmap-ed lesen. Eine andere Möglichkeit ist, wenn das Array im Nur-Lese-Speicher zugeordnet ist.

Bin ich richtig mit meiner Annahme? Ich weiß, dass ich falsch liege, aber warum?

+2

Nein, es greift nicht auf das Element nach dem letzten Element zu. Es erstellt nur einen Zeiger auf ein solches Element, der es jedoch niemals dereferenziert. Dies wird von den relevanten Standards ausdrücklich erlaubt (es ist wichtig, dass die zeigerbasierte Iteration funktioniert). –

+0

'und sogar in C' Nonsense. –

Antwort

3

Ich erinnere mich an das Lesen in der C++ - Standard, dass es gültig war, einen Zeiger auf 1 nach dem letzten Element eines Arrays zu haben (in diesem Fall wäre das &x[5]) aber es ist nie gültig, respektieren es.

Der Code es nicht angezeigt wird gezeigt jemals Ehrerbietung (es dereferenziert nur * es, wenn it < x + max), aber x + max lediglich &x[max] = &x[5] ist, die nach dem C++ Standard gültig ist, aber da der Code nie diesen Wert dereferenziert, der Code gut und funktioniert richtig.

HINWEIS: Versuchen Sie nie zu dereferenzieren etwas wie x [max] das ist nicht definiertes Verhalten im Standard kann schlimme Dinge passieren (Absturz oder schlimmer ...)

0

Wenn die Bedingung it == x+max erreicht, ist die Schleife unterbrochen vor Ausführung der Zeile std::cout << *it << std::endl;.

So funktionieren Schleifen.

  1. führen Sie die Anweisung auto it = x;
  2. die Anweisung auszuführen std::cout << *it << std::endl;
  3. die Anweisung auszuführen ++it
  4. wenn Ausdruck it < x + max true ergibt, zu (2) zurück

wenn it == x + max, die Schleife bricht an (4), ohne auf (2) zurückzuspringen und diesen freien Zeiger zu dereferenzieren.

0

Nein, dieser Code nicht tun, was du sagst. Es gibt keinen Zugriff auf das one-over-the-end-Element.

Es wäre legal, einen Zeiger auf ein solches Element zu haben (so funktionieren schließlich alle Iterator-Bereiche in C++), allerdings nicht zur Dereferenzierung (außer es bezieht sich auf std::string; dann sind Sie garantiert CharT()) . Aber du tust es auch nicht, also ist es in Ordnung.