2016-05-24 3 views
3

Hier ist die A-Code ähnlich wie einen I habe:bereichsbasierte Schleife, einzigartige Zeiger und bewegt Semantik

for (auto &uptr : vector_of_unique_ptrs) {    // 1 
    auto result = do_the_job_with_pointee(uptr.get()); // 2 
    record_intermidiate_result(result, std::move(uptr)); // 3 
} 

Hier habe ich einen Vektor von Zeigern auf einzigartigen einige Objekte (Linie 1).

I iterieren über den Vektor (Zeile 1) und einige Arbeit mit dem Pointee (Zeile 2).

Nachdem der Job fertig ist, muss ich ein Ergebnis machen und das Eigentum an einen anderen Ort übergeben (Zeile 3).

Der Code kompiliert und führt ohne Probleme, aber ich habe das Gefühl, dass es nicht legal ist, iteratee während der Iteration zu verschieben.

Ich "überflogen" obwohl öffentlich zugänglichen C++ 11 Entwurf, aber fand keine Klarstellungen zu diesem Thema.

Kann mir jemand sagen, ob der obige Code legal ist oder nicht?

+5

Ihr Vektor wird 'nullptr'' unique_ptr' haben. – Jarod42

+5

sollten Sie Vektor-Iteratoren nicht ungültig machen, dh rufen Sie 'radiate()' 'insert()' usw. auf. Das Ändern von Elementen ist völlig in Ordnung. – Slava

+1

Ja, jetzt verstehe ich es. Vielen Dank für Ihre Kommentare. – AlexDenisov

Antwort

5
for (auto &uptr : vector_of_unique_ptrs) 

'uptr' ist jetzt eine Referenz auf einen unique_ptr, egal von welchem ​​Typ Sie ihn gemacht haben. 'uptr' ist in diesem Fall kein Iterator. Ihr Code ist also sicher, da er nicht mit dem Iterator verwechselt wird.

Nun, wenn Sie geschrieben hatte, Code wie folgt:

for(auto iter = vec.begin(); iter != vec.end(); iter++) 

, die eine andere Geschichte sein würde. Mit std :: move auf diesem 'Iter' in der Mitte der Schleife wäre problematisch und wahrscheinlich nicht das, was Sie sowieso wollen. Aber die Verwendung Ihres Codes ist sicher, soweit es den Vektor und die Schleife betrifft. In der Tat, hier sind ein paar andere Möglichkeiten, um Ihren Code zu suchen:

//I'm calling your vector_of_unique_ptrs 'vec' for brevity 
//and I'm assuming unique_ptr<int> just 'cause 

//This works 
for (auto iter = vec.begin(); iter != vec.end(); iter++) { 
    unique_ptr<int>& uptr = *iter; 
    auto result = do_the_job_with_pointee(uptr.get()); 
    record_intermidiate_result(result, std::move(uptr)); 
} 

//As does this 
for (size_t i = 0; i < vec.size(); i++) { 
    unique_ptr<int>& uptr = vec[i]; 
    auto result = do_the_job_with_pointee(uptr.get()); 
    record_intermidiate_result(result, std::move(uptr)); 
} 

Und das ist, was der Bereich Basis für Schleife tut; Verwenden Sie einen Iterator und de-referenzieren Sie es für Sie, damit Sie den Iterator nicht wirklich berühren.

+1

Vielen Dank für die ausführliche Antwort. Jetzt ist das Bild in meinem Kopf klar. – AlexDenisov

10

Ihr Code ist absolut legal und klar definiert. Nichts hindert Sie daran, Elemente der Sequenz während der Iteration zu modifizieren, und das Verschieben ist nur eine Form der Modifikation.

Denken Sie daran, nicht zu versuchen, diese Zeiger nach der Schleife zu verwenden.