Does std::copy handle overlapping ranges?

后端 未结 4 2032
萌比男神i
萌比男神i 2021-01-01 14:41

When copying data from one range to another, you have to be careful if there\'s partial overlap between the source and destination ranges. If the beginning of the destinati

相关标签:
4条回答
  • 2021-01-01 15:15

    It seems the most straight forward way would be to create a temporary vector of the range you want to copy:

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

    You can wrap this in a templated function that should be ably to do an overlapped using any container/iterator type.

    0 讨论(0)
  • 2021-01-01 15:20

    It doesn't handle overlapping ranges iff the beginning of the output range overlaps with the input range.

    Fortunately, you can use std::copy_backward instead (which requires that you don't overlap the end of the output range with the input range).

    0 讨论(0)
  • 2021-01-01 15:22

    Preconditions for std::copy, prohibits an overlap:

    • Prototype

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

      • [first, last) is a valid range.
      • result is not an iterator within the range [first, last).
      • There is enough space to hold all of the elements being copied. More formally, the requirement is that [result, result + (last - first)) is a valid range. [1]
    0 讨论(0)
  • 2021-01-01 15:34

    C++17 standard draft

    The C++17 n4659 standard draft says:

    28.6.1 "Copy":

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

    1 Requires: result shall not be in the range [first, last).

    2 Effects: Copies elements in the range [first, last) into the range [result, result + (last - first)) starting from first and proceeding to last.

    and:

    template<class BidirectionalIterator1, class BidirectionalIterator2>
    BidirectionalIterator2
    copy_backward(
        BidirectionalIterator1 first,
        BidirectionalIterator1 last,
        BidirectionalIterator2 result);
    

    17 Requires: result shall not be in the range (first, last].

    18 Effects: Copies elements in the range [first, last) into the range [result - (last-first), result) starting from last - 1 and proceeding to first. (263) For each positive integer n <= (last - first), performs *(result - n) = *(last - n).

    The note then explains when to use copy_backward:

    263) copy_backward should be used instead of copy when last is in the range [result - (last - first), result)

    Therefore, there is no requirement of no overlap for those functions, and unlike for memcpy, the behavior of overlaps is clearly defined in the Effects sections.

    You just choose between them because you usually want std::copy for copying left and std::copy_backward for copying right.

    C++ also has a ranged version of std::move in <algorithm> which moves instead of copying.

    0 讨论(0)
提交回复
热议问题