2009-12-23 7 views
20

Lorsque vous copiez des données d'une plage à une autre, vous devez veiller à ce qu'il y ait un chevauchement partiel entre les plages de source et de destination. Si le début de la plage de destination chevauche la fin de la plage de la source, une copie séquentielle simple déformera les données. La bibliothèque d'exécution C a memmove en plus de memcpy pour gérer de tels problèmes de chevauchement.Est-ce que std :: copy gère les plages de chevauchement?

Je suppose que std::copy fonctionne comme memcpy, en ce sens qu'il ne tient aucun compte du chevauchement entre les régions source et destination. Si vous essayez de déplacer des objets "vers le bas" dans un std::vector avec std::copy, vous corrompez les données. Existe-t-il un algorithme STL analogue à memmove pour gérer des situations comme celle-ci? Ou devrais-je rouler le mien avec des itérateurs inversés?

Répondre

17

Il ne gère pas les plages se chevauchent ssi le début de la plage de sortie chevauche la plage d'entrée.

Heureusement, vous pouvez utiliser std::copy_backward à la place (ce qui exige que vous ne se chevauchent pas la fin de la plage de sortie avec la plage d'entrée).

+0

'std :: copy_backward' serait utile en essayant de mettre en œuvre et analogue de' memmove'. Je veux prendre la vérification du fardeau de chevauchement de l'appelant. –

9

Conditions préalables à std::copy, interdit un chevauchement:

  • Prototype

    template <class InputIterator, class OutputIterator> 
    OutputIterator copy(InputIterator first, InputIterator last, 
            OutputIterator result); 
    
  • Préconditions

    • [first, last) est une plage valide. Le résultat n'est pas un itérateur dans la plage [first, last).
    • Il y a suffisamment d'espace pour contenir tous les éléments en cours de copie. Plus formellement, l'exigence est que [result, result + (last - first)) est une plage valide . [1]
+0

Cela répond à la question dans le titre. La question restante est de savoir s'il existe un analogue de 'memmove' ou si je dois lancer le mien. –

+3

Cela interdit seulement un chevauchement avec le début de la plage de destination. Comme le dit John, un chevauchement avec le milieu ou la fin est autorisé, et 'std :: copy_backward' permet un chevauchement avec le début (mais pas la fin). –

0

Il semble la voie la plus directe serait de créer un vecteur temporaire de la plage que vous souhaitez copier:

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

Vous pouvez envelopper cela dans une fonction basé sur un modèle qui devrait être habilement à faire une chevauché en utilisant tout type de conteneur/itérateur.

+2

Oui, mais cela pourrait conduire à beaucoup plus de copie que nécessaire. Je préfère utiliser une fonction qui teste le chevauchement, puis utilise la bonne technique de copie pour le mettre en place. –