关于std::copy 中的overlapped问题解释

转自 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.

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值