std :: copy是否处理重叠范围?

时间:2009-12-23 13:59:29

标签: c++ algorithm stl copy

将数据从一个范围复制到另一个范围时,如果源范围和目标范围之间存在部分重叠,则必须小心。如果目标范围的开头与源范围的尾部重叠,则普通顺序副本将使数据混乱。除了memmove之外,C运行时库还有memcpy来处理此类重叠问题。

我认为std::copy的作用类似于memcpy,因为它不会考虑源和目标区域之间的重叠。如果您尝试使用std::vectorstd::copy中“向下”移动对象,则会损坏数据。是否有memmove的STL算法模拟来处理这样的情况?或者我应该使用反向迭代器自己动手?

4 个答案:

答案 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标准草案

C++17 n4659 standard draft说:

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 memcpyEffects部分中明确定义了重叠行为。

您只需在它们之间进行选择,因为您通常希望std::copy用于向左复制,std::copy_backward用于向右复制。

C ++在std::move中还有一个<algorithm>的范围版本,可以移动而不是复制。