2009-12-23 16 views
20

Quando si copiano dati da un intervallo a un altro, è necessario fare attenzione se si verifica una sovrapposizione parziale tra l'intervallo di origine e quello di destinazione. Se l'inizio dell'intervallo di destinazione si sovrappone alla coda dell'intervallo di origine, una semplice copia sequenziale condannerà i dati. La libreria di runtime C ha memmove oltre a memcpy per gestire tali problemi di sovrapposizione.std :: copy gestisce intervalli sovrapposti?

Suppongo che il numero std::copy funzioni come memcpy, in quanto non si tiene conto della sovrapposizione tra le regioni di origine e di destinazione. Se provi a spostare gli oggetti "in basso" in un std::vector con std::copy, i dati verranno corretti. Esiste un algoritmo STL analogico di memmove per gestire situazioni come questa? O dovrei girare il mio con iteratori inversi?

risposta

17

Non gestisce sovrapposti intervalli sse il inizio del campo di uscita si sovrappone con il campo di ingresso.

Fortunatamente, è possibile utilizzare std::copy_backward invece (che richiede che non si sovrappongono alla fine del campo di uscita con il campo di ingresso).

+0

'std :: copy_backward' sarebbe utile nel tentativo di implementare e analogare' memmove'. Voglio controllare la sovrapposizione del carico del chiamante. –

9

Presupposti per std::copy, vieta una sovrapposizione:

  • prototipo

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

    • [first, last) è un intervallo valido.
    • risultato non è un iteratore all'interno della gamma [first, last).
    • c'è abbastanza spazio per contenere tutti gli elementi da copiare. Più formalmente, il requisito è che [result, result + (last - first)) è un intervallo valido . [1]
+0

Questo risponde alla domanda nel titolo. La domanda rimanente è se ci sia un analogo di "memmove" o se devo girare il mio. –

+3

Ciò impedisce solo una sovrapposizione con l'inizio dell'intervallo di destinazione. Come dice John, è consentita una sovrapposizione con il centro o la fine e 'std :: copy_backward' consente una sovrapposizione con l'inizio (ma non la fine). –

0

Sembra che la via da seguire più dritto sarebbe quello di creare un vettore temporanea del campo da copiare:

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

si può avvolgere questo in una funzione template che dovrebbe essere abilmente per fare un sovrapposto utilizzando qualsiasi tipo di contenitore/iteratore.

+2

Sì, ma questo potrebbe portare a molte più copie del necessario. Preferirei una funzione che verifica la sovrapposizione e quindi utilizza la tecnica di copia corretta per farlo al suo posto. –

Problemi correlati