将数据从一个范围复制到另一个范围时,如果源范围和目标范围之间存在部分重叠,则必须小心。如果目标范围的开头与源范围的尾部重叠,则普通顺序副本将使数据混乱。除了memmove
之外,C运行时库还有memcpy
来处理此类重叠问题。
我认为std::copy
的作用类似于memcpy
,因为它不会考虑源和目标区域之间的重叠。如果您尝试使用std::vector
在std::copy
中“向下”移动对象,则会损坏数据。是否有memmove
的STL算法模拟来处理这样的情况?或者我应该使用反向迭代器自己动手?
答案 0 :(得分:18)
如果输出范围的开始与输入范围重叠,则不处理重叠范围。
幸运的是,您可以使用 std::copy_backward
(这要求您不要将输出范围的 end 与输入范围重叠)。< / p>
答案 1 :(得分:9)
std::copy
的先决条件,禁止重叠:
原型
template <class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
前提条件
[first, last)
是有效范围。- 结果不是
[first, last)
范围内的迭代器。- 有足够的空间来容纳所有被复制的元素。更多 正式地说,要求就是这样
[result, result + (last - first))
是一个 有效范围。 [1]
答案 2 :(得分:0)
似乎最直接的方法是创建要复制的范围的临时矢量:
std::vector copiedRange( srcVecIterBegin, srcVecIterEnd);
std::copy( copiedRange.begin(), copiedRange.end(), srcVecIterCopyLocIter);
你可以将它包装在一个模板化的函数中,该函数应该可以使用任何容器/迭代器类型进行重叠。
答案 3 :(得分:0)
C ++ 17标准草案
28.6.1“复制”:
template<class InputIterator, class OutputIterator> OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result);
1要求:结果不得在[first,last)范围内。
2效果:将[first,last)范围内的元素复制到[result,result +(last- first))从头开始,一直到最后。
和:
template<class BidirectionalIterator1, class BidirectionalIterator2> BidirectionalIterator2 copy_backward( BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result);
17要求:结果不得在范围内(第一个,最后一个)。
18个效果:将[first,last)范围内的元素复制到[result-(last-first), 结果)从最后一个开始-1,然后进行到第一个。 (263)对于每个正整数n <=(最后- first),执行*(result-n)= *(last-n)。
然后,注释说明了何时使用copy_backward
:
263)当last在[结果-(last-first),结果)范围内时,应使用copy_backward而不是copy
因此,这些功能不要求没有重叠,并且unlike for memcpy
在Effects
部分中明确定义了重叠行为。
您只需在它们之间进行选择,因为您通常希望std::copy
用于向左复制,std::copy_backward
用于向右复制。
C ++在std::move
中还有一个<algorithm>
的范围版本,可以移动而不是复制。