C++ 标准::复制,标准::向后复制和重叠范围
我指的是和 模板<类输入,类输出>输出副本(输入 首先,最后输入,首先输出d_) 从第一个和第二个开始复制[第一个,最后一个]范围内的所有元素 继续到last-1。如果d_first在 范围[first,last]。在这种情况下,可以使用std::copy_backward 相反 模板C++ 标准::复制,标准::向后复制和重叠范围,c++,c++11,stdcopy,C++,C++11,Stdcopy,我指的是和 模板输出副本(输入 首先,最后输入,首先输出d_) 从第一个和第二个开始复制[第一个,最后一个]范围内的所有元素 继续到last-1。如果d_first在 范围[first,last]。在这种情况下,可以使用std::copy_backward 相反 模板BidirIt2向后复制( BidirIt1 first,BidirIt1 last,BidirIt2 d_last) 将元素从[first,last]定义的范围复制到 另一个范围以d_last结尾。元素被反向复制 顺序(首先复制最
#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);
}
显然,copy会产生预期的结果,而copy_backward不会,即使d_first在范围[first,last]内。此外,d_last也在范围(first,last]内,根据文档,在向后复制的情况下,这将导致未定义的行为
因此,实际上,在向后复制的情况下,程序输出与文档一致,而在复制的情况下则不一致
值得再次注意的是,在这两种情况下,d_first和d_last确实满足了条件,根据文档,这将分别导致copy和copy_backward的未定义行为。然而,只有在copy_backward的情况下才观察到未定义的行为。这里没有深入的内容。只需运行一个算法即可-使用一种简单的方法完成示例数据:按顺序复制每个元素 假设你有一个四元素数组
inta[4]={0,1,2,3}
,你想把前三个元素复制到后三个元素。理想情况下,你会得到{0,0,1,2}
。这(不是)如何处理std::copy(a,a+3,a+1)
步骤1:复制第一个元素a[1]=a[0];
数组现在是{0,0,2,3}
步骤2:复制第二个元素a[2]=a[1];
数组现在是{0,0,3}
步骤3:复制第三个元素a[3]=a[2];
数组现在是{0,0,0}
结果是错误的,因为您在读取某些源数据(a[1]
和a[2]
)之前重写了这些数据。反向复制会起作用,因为按照相反的顺序,您会先读取值,然后再覆盖它们
由于一种合理的方法的结果是错误的,因此标准宣布行为为“未定义”。希望采用幼稚方法的编译器可能会,并且他们不必考虑这种情况。在这种情况下,错误是可以的。采用不同方法的编译器可能会产生不同的结果,甚至可能是“正确的”结果。这也没关系。根据标准,编译器最简单的方法都可以
根据问题的补充:请注意,这并不意味着行为被定义为违背程序员的意图,而是意味着行为不是由C++标准定义的。它由每个编译器决定发生什么。<代码> STD::拷贝(A,A + 3,A+ 1)可以是任何东西。您可能会得到
{0,0,0,0}
的原始结果。但是,您可能会得到{0,0,1,2}的预期结果
。其他结果也是可能的。你不能仅仅因为幸运地获得了你想要的行为就断定没有未定义的行为。有时,未定义的行为会给出正确的结果。(这就是跟踪与未定义行为相关的错误非常困难的原因之一。)原因是,一般来说,复制ran的一部分
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