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

发布于 2024-08-15 18:54:06 字数 351 浏览 2 评论 0原文

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

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

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 destination range overlaps the tail of the source range, a plain sequential copy will garble the data. The C run-time library has memmove in addition to memcpy to handle such overlap problems.

I assume std::copy works like memcpy, in that it doesn't pay any regard to overlap between the source and destination regions. If you try to shift objects "down" in a std::vector with std::copy, you'll corrupt the data. Is there an STL algorithm analogue of memmove to handle situations like this? Or should I roll my own with reverse iterators?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

川水往事 2024-08-22 18:54:06

如果输出范围的开头与输入范围重叠,它不会处理重叠范围。

幸运的是,您可以使用 std::copy_backward< /a> 相反(这要求您不要将输出范围的末尾与输入范围重叠)。

It doesn't handle overlapping ranges if 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).

凉城凉梦凉人心 2024-08-22 18:54:06

std::copy 的先决条件,禁止重叠:

  • 原型

    模板 ;
    OutputIterator 复制(InputIterator 首先,InputIterator 最后,
                        输出迭代器结果);
    
  • 先决条件

    • [first, last) 是有效范围。
    • 结果不是 [first, last) 范围内的迭代器。
    • 有足够的空间来容纳所有正在复制的元素。更多的
      形式上,要求是
      [结果,结果+(最后 - 第一个)) 是一个
      有效范围。 [1]

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]
瞳孔里扚悲伤 2024-08-22 18:54:06

C++17 标准草案

C+ +17 n4659 标准草案 说:

28.6.1“复制”:

template;
OutputIterator 复制(InputIterator 首先,InputIterator 最后,
                    输出迭代器结果);

1 要求:结果不得在 [first, last) 范围内。

2 效果:将 [first, last) 范围内的元素复制到 [result, result + (last -
first)) 从第一个开始一直到最后一个。

和:

模板
双向迭代器2
向后复制(
    首先是双向迭代器1,
    双向迭代器1 最后,
    双向迭代器2结果);

17 要求:结果不得在范围(第一个、最后一个]内。

18 效果:将 [first, last) 范围内的元素复制到 [result - (last-first),
结果)从最后一个 - 1 开始并继续到第一个。 (263) 对于每个正整数 n <= (最后 -
首先),执行 *(结果 - n) = *(最后 - n)。

该注释随后解释了何时使用 copy_backward

263) 当最后一个位于 [结果 - (最后 - 第一个), 结果) 范围内时,应使用 copy_backward 而不是复制

因此,不要求这些函数不重叠,并且 memcpy 不同,重叠的行为在 Effects 中明确定义部分。

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

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

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.

浅忆 2024-08-22 18:54:06

似乎最直接的方法是创建要复制的范围的临时向量:

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

您可以将其包装在模板化函数中,该函数应该能够使用任何容器/迭代器类型进行重叠。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文