Ich habe im C ++ - Standard nach N3485 25.3.1 [alg.copy] gesucht, der 4 Algorithmen definiert:
copy
copy_backward
copy_if
copy_n
In der Beschreibung für copy
gibt es diesen Hinweis 25.3.1 [alg.copy] / 3:
Erfordert: Das Ergebnis darf nicht im Bereich [first, last]
liegen
Das heißt, copy
funktioniert nicht immer korrekt, wenn sich die Bereiche überschneiden (ähnlich wie memcpy
).
copy_backward
und copy_if
haben ähnliche Sprachen, die überlappende Bereiche verbieten (25.3.1 [alg.copy] / 14 bzw. 25.3.1 [alg.copy] / 8).
Allerdings gibt es kein solches Verbot für copy_n
, und es gibt kein copy_n_backward
. Bedeutet dies, dass copy_n
das Richtige tut, wenn sich die Bereiche überschneiden?
(Die Implementierung von copy_n
von MSVC ++ scheint an std::memmove
zu delegieren, also weiß ich, dass es hier auf MSVC ++ 2013 sicher ist. Aber ich möchte mich nicht darauf verlassen, wenn der Standard das Gegenteil verspricht)
Es ist sicher *. Warum? Weil der Standard nicht sagt, dass nicht sicher ist. Sie kopieren Funktionen aus 25.3.1 have Benötigt: für Dinge, die sie benötigen (hier ist das Überschneidungsverbot in den anderen Kopierformen angegeben).
Allerdings sagt copy_n
nicht , dass die Bereiche sich nicht überlappen müssen, was bedeutet, dass es in Ordnung ist, da es nicht explizit verboten ist. Wenn es es erfordert, würde es es sagen.
* Edit: Wenn ich "sicher" meinte, meinte ich, dass es kein undefiniertes Verhalten oder ein schlechtes Programm ist. Die Ergebnisse sind jedoch nicht garantiert, was Sie wahrscheinlich beabsichtigten, wenn sich die Speicherbereiche überschneiden. Das Einzige, was wir garantieren können, ist:
i < n
wird *(result + i) = *(first + i)
durchgeführt Daraus können wir ableiten, dass, wenn sich die Bereiche überschneiden, die im Ziel gespeicherten Ergebnisse nicht mehr garantiert sind, um eine exakte (in der richtigen Reihenfolge) Kopie der Quelle zu sein. Wir garantieren, dass jeder Wert im Ziel von der Quelle kommt, obwohl genau welche Werte diese sind, hängt von der Überlappung und der genauen Reihenfolge ab, in der die Elemente kopiert werden.
Wenn du also unter "sicher" meinst, dass das Ziel immer eine perfekte Kopie der Quelle hat (wie memmove
), dann ist es nicht "sicher". Aber es ist sicher in dem Sinne, dass es nicht undefiniert / ungültiges Verhalten an und für sich selbst verursacht.
Zur Erinnerung, wir garantieren, dass *(result + i) = *(first + i)
für jedes Element im gesamten Bereich ausgeführt wird. Es wird garantiert, dass das Programm bei Überlappung der Bereiche immer noch nicht undefiniert ist. Die Reihenfolge, in der die Elemente kopiert werden, ist nicht gewährleistet. Es ist nicht garantiert, dass, wenn sich die Bereiche überschneiden, die genauen Werte im Ergebnis gespeichert werden (aber wir wissen, dass sie alle aus der Quelle stammen).
Ich stimme Cornstalks 'Antwort zu und stimme ihr +1 zu. Aber Theorie muss durch Übung unterstützt werden.
Ein kurzer Blick auf die Implementierungen von GCC (libstdc ++ - v3) und Clang (libc ++) zeigt, dass ihr copy_n
dasselbe ist (oder delegiert an) copy
, ohne Unterstützung für Überlappungen beim Verschieben von Objekten nach höher Adressen.
Also gewinnt MSVC diese Runde, zumindest im POD-Fall, der an memmove
delegiert.
Tags und Links algorithm c++ stl stl-algorithm