Copy_backward или копировать с помощью reverse_iterators?

В терминах практического использования существуют различия между

a) copy_backward

b) копировать с помощью reverse_iterators для источника и адресата

В частности, это более общеприменимо, чем другое? Есть ли другие отличия?

Обновление: если на самом деле нет разницы, то любая ссылка в литературе С++ на эту эквивалентность оценивается. Мотивация, стоящая за этим вопросом, заключается в том, чтобы понять, было ли это по дизайну или одному из этих промахов (например, missing copy_if)

Ответ 1

Прежде всего, использование copy_backward() явно показывает намерение разработчика скопировать интервал в обратном порядке.

copy_backward() работает с оригинальными двунаправленными итераторами, в то время как reverse_iterator является адаптером двунаправленного итератора и может быть не таким эффективным, как оригинальный итератор.

Использование reverse_iterator имеет смысл, когда вам нужно применить алгоритм ввода итераторов типа copy() для обратной последовательности, но не иметь аналогов для двунаправленных операторов, таких как copy_backward().

Поэтому существуют концептуальные и практические различия.

Ответ 2

http://www.cplusplus.com/reference/algorithm/copy/ имеет реализацию std::copy

http://www.cplusplus.com/reference/algorithm/copy_backward/ имеет реализацию std::copy_backward

Вы можете увидеть различия самостоятельно.

Примечание.. Если бы я был вами, я бы использовал std::copy_backward, потому что вызов std::copy с классом std::reverse_iterator<T> может быть немного медленнее (для этого требуется больше памяти, чем двунаправленный итератор)

Ответ 3

Разница в том, что copy возвращает итератор в элемент pass-end, а copy_backward возвращает итератор в первый элемент.

В этом смысле они не эквивалентны.

  • Подписи, конечно, различаются. copy в порядке с InputIterator и OutputIterator. Пока copy_backward ожидает BidirectionalIterator s.
  • Влияние на контейнер (при правильном использовании) одинаково, но возвращенные итераторы имеют разные типы и указывают на разные элементы.

Пример:

Это работает, потому что vector может использовать RandomAccessIterator, который поддерживает свойства, ожидаемые InputIterator, OutputIterator и BidirectionalIterator.

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void printer(int i) {
    cout << i << ", ";
}

int main() {

    int mynumbers[] = {3, 9, 0, 2, 1, 4, 5};
    vector<int> v1(mynumbers, mynumbers + 7);

    vector<int>::iterator it = copy_backward(mynumbers, mynumbers + 7, v1.end());
    for_each(v1.begin(), v1.end(), printer);
    cout << endl << "Returned element: " << *it;
    cout << endl;

    vector<int>::reverse_iterator rit = copy(mynumbers, mynumbers + 7, v1.rbegin());
    for_each(v1.begin(), v1.end(), printer);
    cout << endl << "Before the first element (reverse end)? " << (rit == v1.rend());
    rit--; // go to first element, because it is a reverse iterator
    cout << endl << "Returned element: " << *rit;

    return 0;
}

Результат:

3, 9, 0, 2, 1, 4, 5, 
Returned element: 3
5, 4, 1, 2, 0, 9, 3, 
Before the first element (reverse end)? 1
Returned element: 5

Если вы используете контейнер, который не поддерживает BidirectionalIterator, тогда вы рискуете неприятностями (например, если вы попытаетесь скопировать назад a forward_list, потому что он использует ForwardIterator, который не поддерживает выполняемые операции на BidirectionalIterator).
Также в этом случае копирование с обратным итератором на forward_list также невозможно, так как оно не поддерживает обратные итераторы.

В принципе, вам нужно убедиться, что итераторы контейнера поддерживаются и выбирают в зависимости от того, какой конец контейнера вы хотели бы вернуть. В противном случае эффект будет таким же.

Ответ 4

Никаких различий практически нет. Аналогичным образом вы можете сравнить форматированное копирование.

a) скопировать

b) copy_backward с обратными итераторами.

Ответ 5

Однако не должно быть никакой разницы: copy_backward пригодится в случае, если итератор является результатом некоторого вызова функции, а также намного чище, чем использование копии с помощью обратных итераторов.