我的参考是std::copy和std::copy_backward。
template< class InputIt, class OutputIt > OutputIt copy( InputIt first, InputIt last, OutputIt d_first );
复制范围 [first, last) 中的所有元素,从 first 开始,一直到 last - 1。如果 d_first 在 [first, last) 范围内,则行为未定义。在这种情况下,可以使用 std::copy_backward 代替。
模板< class BidirIt1, class BidirIt2 > BidirIt2 copy_backward( BidirIt1 first, BidirIt1 last, BidirIt2 d_last )
将由 [first, last) 定义的范围中的元素复制到以 d_last 结尾的另一个范围。以相反的顺序复制元素(首先复制最后一个元素),但保留它们的相对顺序。
如果 d_last 在 (first, last] 之内,则行为未定义。在这种情况下,必须使用 std::copy 而不是 std::copy_backward。
复制重叠范围时,std::copy 适用于向左复制(目标范围的开头在源范围之外),而 std::copy_backward 适用于向右复制(目标范围的结尾在源范围之外)范围)。
根据以上描述,我得出以下推论:
copy 和 copy_backward 最终都将相同的源范围 [first, last) 复制到目标范围,尽管在前者的情况下,复制从第一个到最后一个 - 1,而在后者的情况下,复制从最后一个发生-1 到第一。在这两种情况下,源范围中元素的相对顺序都会保留在结果目标范围中。
但是,以下两个规定背后的技术原因是什么:
1) 在复制的情况下,如果 d_first 在 [first, last) 范围内,则会导致未定义的行为(暗示将源范围复制到目标范围的不成功以及可能的系统故障)。
2) 在 copy_backward 的情况下,如果 d_last 在范围内(第一个,最后一个),则会导致未定义的行为(暗示将源范围复制到目标范围的不成功以及可能的系统故障)。
我假设一旦我理解了上述两个语句的含义,将 copy 替换为 copy_backward 以避免上述未定义行为场景的建议对我来说将变得显而易见。
同样,我还假设在向左复制时提到复制的适当性(我不清楚这个概念),以及在向右复制时的 copy_backward(我也不清楚这个概念),将开始一旦我理解了 copy 和 copy_backward 之间的上述区别,就有意义了。
一如既往地期待您的有益想法。
附录
作为后续,我编写了以下测试代码来验证 copy 和 copy_backward 的行为,以实现相同的操作。
#include <array>
#include <algorithm>
#include <cstddef>
#include <iostream>
using std::array;
using std::copy;
using std::copy_backward;
using std::size_t;
using std::cout;
using std::endl;
int main (void)
{
const size_t sz = 4;
array<int,sz>a1 = {0,1,2,3};
array<int,sz>a2 = {0,1,2,3};
cout << "Array1 before copy" << endl;
cout << "==================" << endl;
for(auto&& i : a1) //the type of i is int&
{
cout << i << endl;
}
copy(a1.begin(),a1.begin()+3,a1.begin()+1);
cout << "Array1 after copy" << endl;
cout << "=================" << endl;
for(auto&& i : a1) //the type of i is int&
{
cout << i << endl;
}
cout << "Array2 before copy backward" << endl;
cout << "===========================" << endl;
for(auto&& i : a2) //the type of i is int&
{
cout << i << endl;
}
copy_backward(a2.begin(),a2.begin()+3,a2.begin()+1);
cout << "Array2 after copy backward" << endl;
cout << "==========================" << endl;
for(auto&& i : a2) //the type of i is int&
{
cout << i << endl;
}
return (0);
}
以下是程序输出:
Array1 before copy
==================
0
1
2
3
Array1 after copy
=================
0
0
1
2
Array2 before copy backward
===========================
0
1
2
3
Array2 after copy backward
==========================
2
1
2
3
显然, copy 会产生预期的结果,而 copy_backward 不会,即使 d_first 在 [first, last) 范围内。此外, d_last 也在范围内(第一个,最后一个),根据文档,这应该会在 copy_backward 的情况下导致未定义的行为。
所以实际上,在copy_backward的情况下,程序输出与文档一致,而在copy的情况下则不是。
再次值得注意的是,根据文档,在这两种情况下, d_first 和 d_last 确实满足分别导致 copy 和 copy_backward 未定义行为的条件。但是,仅在 copy_backward 的情况下才会观察到未定义的行为。