2017-01-30 9 views
2

Ich habe kürzlich über die Regeln für Zeigerarithmetik in C++ nachgedacht, nachdem ich gelernt habe, dass Zeigerarithmetik nur für Zeiger definiert ist, die auf Objekte zeigen, die in einem Array existieren.C++ Iterieren eines Elements - UB oder definiertes Verhalten?

Dies führte mich zu der Frage, ob das Verhalten des folgenden Codes nach dem Standard streng undefiniert ist.

Kann jemand Licht abgeben?

#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <utility> 
#include <string> 
#include <vector> 

struct Thing { 
    std::string val; 
}; 

int main() { 

    Thing a_thing; 

    std::vector<Thing> things; 

    // take address 
    auto first_thing = std::addressof(a_thing); 

    // take address of "one past the end" - UB? 
    auto last_thing = std::next(first_thing);  

    // copying exactly one item, but is it UB? 
    std::copy(first_thing, last_thing, std::back_inserter(things)); 
} 
+0

vielen dank für die schnelle antwort –

Antwort

2

Das Programm ist wohlgeformt.

Sie dürfen einen Zeiger hinter dem Ende eines Arrays oder sogar direkt hinter der Adresse eines Skalars setzen, als wäre es ein einzelnes Element-Array.

Dieser zweite Teil ist hier wichtig. Solange Sie nicht wirklich dereferencelast_thing, die std::copy wird nicht, wird Ihr Code perfekt laufen.

4

Nach 5,7 [expr.add] Ziffer 4 ein Zeiger auf ein Objekt verhält sich wie ein Zeiger, um das erste Objekt aus einer einem Element-Array:

Für die Zwecke dieser Operatoren, einen Zeiger auf eine Nonarray Objekt verhält sich genauso wie ein Zeiger auf das erste Element eines Arrays der Länge eins mit dem Typ des Objekts als Elementtyp.

3

Dies ist wohlgeformt.

[expr.add]/4 Zustände:

Für die Zwecke dieser Operatoren, ein Zeiger auf ein Objekt Nonarray verhält sich wie ein Zeiger auf das erste Element aus einer Anordnung von einer Länge mit dem Typ des Objekts als Elementtyp.

nach dem es wird festgestellt ([expr.add]/5):

Wenn sowohl der Zeigeroperanden und das Ergebnis Punkt Elemente des gleichen Array-Objekt oder ein letzten Das letzte Element des Array-Objekts, die Auswertung soll keinen Überlauf erzeugen; Andernfalls ist das Verhalten undefined.

Hervorhebung von mir.

3

Wie die anderen Antworten erwähnt, ist Ihr Programm wohlgeformt. Hier ist der relevante standardese aus dem aktuellen Arbeitspapier:

§5.7 (footnote 86) [expr.add]

Ein Objekt, das nicht ein Array-Element wird als für diesen Zweck eine Einzelelement-Array gehören; siehe [expr.unary.op]. Ein Zeiger hinter dem letzten Element eines Arrays x von n Elementen wird als äquivalent zu einem Zeiger auf ein hypothetisches Element x[n] für diesen Zweck angesehen; siehe [basic.compound].

Kurz gesagt, ein nicht-Array-Objekt verhält sich wie ein Einzelelement-Array im Kontext der Zeigerarithmetik. Die Annahme einer End-zu-End-Adresse ist daher legal.

Verwandte Themen