2009-12-23 14 views
20

Wenn Sie Daten von einem Bereich in einen anderen kopieren, müssen Sie vorsichtig sein, wenn sich der Quell- und der Zielbereich teilweise überschneiden. Wenn der Anfang des Zielbereichs mit dem Ende des Quellbereichs überlappt, werden die Daten bei einer einfachen sequenziellen Kopie unverfälscht. Die C-Laufzeitbibliothek hat memmove zusätzlich zu memcpy, um solche Überlappungsprobleme zu behandeln.Behandelt std :: copy überlappende Bereiche?

Ich gehe davon aus, std::copy funktioniert wie memcpy, in dem es keine Rücksicht auf die Überlappung zwischen den Quell-und Zielregionen zahlt. Wenn Sie versuchen, Objekte in einem std::vector mit std::copy "nach unten" zu verschieben, werden Sie die Daten beschädigen. Gibt es einen STL-Algorithmus analog zu memmove, um Situationen wie diese zu behandeln? Oder sollte ich selbst mit umgekehrten Iteratoren rollen?

Antwort

17

Es behandelt nicht die Bereiche iff beginnend des Ausgangsbereichs überlappt mit dem Eingabebereich überlappt.

Glücklicherweise können Sie std::copy_backward stattdessen verwenden (was erfordert, dass Sie nicht des Ausgangsbereichs mit dem Eingangsbereich des Ende überlappen).

+0

'std :: copy_backward' wäre hilfreich bei der Implementierung von 'memmove' und analog dazu. Ich möchte die Prüfung auf Überlappungslast vom Anrufer nehmen. –

9

Voraussetzungen für std::copy verbietet eine Überlappung:

  • Prototype

    template <class InputIterator, class OutputIterator> 
    OutputIterator copy(InputIterator first, InputIterator last, 
            OutputIterator result); 
    
  • Voraussetzungen

    • [first, last) ist ein gültiger Bereich.
    • Ergebnis ist kein Iterator im Bereich [first, last).
    • Es ist genügend Platz vorhanden, um alle zu kopierenden Elemente aufzunehmen. Mehr formal ist die Anforderung, dass [result, result + (last - first)) ein gültigen Bereich ist. [1]
+0

Das beantwortet die Frage im Titel. Die verbleibende Frage ist, ob es ein Analogon von "memmove" gibt oder ob ich selbst rollen muss. –

+3

Das verbietet nur eine Überschneidung mit dem Start des Zielbereichs. Wie John sagt, ist eine Überlappung mit der Mitte oder dem Ende erlaubt, und "std :: copy_backward" erlaubt eine Überlappung mit dem Start (aber nicht das Ende). –

0

Es scheint, der direkteste Weg, um eine temporäre Vektor des Bereichs, den Sie kopieren möchten erstellen wäre:

std::vector copiedRange(srcVecIterBegin, srcVecIterEnd); 
std::copy(copiedRange.begin(), copiedRange.end(), srcVecIterCopyLocIter); 

Sie dies in einer Templat-Funktion wickeln können, die geschickt eine überlappte sein sollte zu tun mit beliebiger Container/Iterator-Typ

+2

Ja, aber das könnte zu viel mehr Kopieren als nötig führen. Ich würde lieber eine Funktion korrigieren, die nach Überlappungen sucht, und dann die richtige Kopiermethode verwenden, um das zu tun. –

Verwandte Themen