转自 http://www.trilithium.com/johan/2006/02/copy-confusion/
The standard C++ library contains std::copy which is the generic equivalent to the Cmemcpy function. There's nothing stopping you from using std::memcpy in C++ as well – but why would you do that when there's a replacement that's capable of working with all kinds of iterators while being just as efficient as memcpy for built-in types?
Indeed, once you start std::copying there should be no need to look back. However, if you're familiar with memcpy you must also be aware that it cannot be used if the source and destination memory areas overlap. Let's take a look at the std::copy description to see if it has a similar limitation:
template <class InIt, class OutIt>
OutIt copy(InIt first, InIt last, OutIt result);
- Effects: Copies elements in the range [first, last) into the range [result, result + (last - first)) starting from first and proceeding to last.
- Returns: result + (last - first)
- Requires: result shall not be in the range [first, last).
- Complexity: Exactly last - first assignments.
Aha! That requirement could certainly prove to be a problem when we're copying overlapping ranges. In C we're supposed to use the memmove function if the source and destination overlap. Surely C++ must offer us something for when std::copy can't do the job? Yes, of course it does:
template <class BidIt1, class BidIt2>
BidIt2 copy_backward(BidIt1 first, BidIt1 last, BidIt2 result);
- Effects: Copies elements in the range [first, last) into the range [result - (last - first), result) starting from last - 1 and proceeding to first.
- Returns: result - (last - first)
- Requires: result shall not be in the range [first, last).
- Complexity: Exactly last - first assignments.
Hey, std::copy_backward has the exact same requirement of result not being in the source range! How am I supposed to copy overlapping ranges? Where is my genericmemmove?
It's easy, especially for a someone with a strong C background looking for memmove, to draw the wrong conclusion from the iterator requirements. Read the descriptions again carefully. Nothing is said about overlapping ranges, only that result can't be in the source range. When there is overlap at the start of the source range, std::copy will work fine:
True to its name, std::copy_backward will copy backwards, so result actually marks the end of the region when you call this function. That covers the case where overlap occurs at the end of the source range:
Both std::copy and std::copy_backward can in fact deal with overlap, you just have to call the correct one depending on the situation. Typically you don't even need to compare iterators to determine which function to call because you already know what kind of overlap you have at the call site.
There is no std::move that does the right thing automatically. Such a function could be written, but it would be less general as well as less efficient than the two existing copy functions; it would have to compare destination and source range iterators every time.