Мои ссылки на std :: copy и std :: copy_backward .
template <класс InputIt, класс OutputIt> OutputIt copy (InputItfirst, InputIt last, OutputIt d_first);
Копирует все элементы в диапазоне [first, last) начиная с первого и заканчивая последним - 1. Поведение не определено, если d_first находится в диапазоне [first, last). В этом случае вместо этого можно использовать std :: copy_backward.
template <класс BidirIt1, класс BidirIt2> BidirIt2 copy_backward (сначала BidirIt1, 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 endдо того же самого исходного диапазона [first, last) до целевого диапазона, хотя в первом случае копирование происходит с первого до последнего - 1, тогда как в случае последнего копирование происходит с последнего -1 до первого. В обоих случаях относительный порядок элементов в исходном диапазоне сохраняется в результирующем целевом диапазоне.
Однако, какова техническая причина, лежащая в основе следующих двух условий:
1) В случаекопирования, неопределенные результаты поведения (подразумевающие неудачное копирование исходного диапазона в целевой диапазон и, возможно, системную ошибку), если d_first находится в пределах диапазона [first, last).
2) В случае copy_backward, undefinedрезультаты поведения (подразумевающие неудачное копирование исходного диапазона в целевой диапазон и, возможно, системную ошибку), если d_last находится в пределах диапазона (первый, последний).
Я предполагаю, что предложение заменить copy на copy_backward для avertописанный выше неопределенный сценарий поведения станет для меня очевидным, как только я пойму смысл двух приведенных выше утверждений.
Аналогично, я также предполагаю, что упоминание о целесообразности копирования при копировании влево (какое понятиене понятно мe) и 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_backward - нет, даже если d_first находится в диапазоне [first, last). Кроме того, d_last также находится в пределах диапазона (first, last), что должно привести к неопределенному поведению в случае copy_backward в соответствии с документацией.
Таким образом, выходные данные программы соответствуют документациив случае copy_backward, тогда как в случае копирования это не так.
Стоит еще раз отметить, что в обоих случаях d_first и d_last удовлетворяют условию, которое должно привести к неопределенному поведению как для copy, так и для copy_backward. соответственно, согласно документации. Однако неопределенное поведение наблюдается только в случае copy_backward.