Реализация STL-копии - PullRequest
       23

Реализация STL-копии

1 голос
/ 08 декабря 2011

Ниже приводится определение копии в соответствии с http://www.sgi.com/tech/stl/copy.html.

template<class InputIterator, class OutputIterator>
  OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
   while (first != last) *result++ = *first++;
   return result;
}

Я написал следующий код.

vector<int> v;
set<int> s;

s.insert(7);
s.insert(11);
s.insert(27);

//copy elements from the set into the vector
copy(s.begin(), s.end(), v.begin());

Почему при вызове copy выше выдается ошибка времени выполнения, а не ошибка компиляции? Я предполагаю, что это связано с тем фактом, что вектор пуст, v.begin () == v.end (). Но почему?

Кроме того, я исправил код, изменив его следующим образом.

copy(s.begin(), s.end(), back_inserter(v));

Функция back_inserter возвращает итератор типа back_insert_iterator>. Почему это работает? Что он делает?

Ответы [ 2 ]

2 голосов
/ 08 декабря 2011

Сбой, потому что вы не соблюдаете третье предварительное условие, указанное на этом же сайте:

Достаточно места для хранения всех копируемых элементов. Больше формально требование состоит в том, чтобы [result, result + (last - first)) допустимый диапазон. [1]

Пустой вектор меньше, чем набор из 3 элементов, поэтому вы не можете выполнить операцию копирования (которая действительно должна называться операцией перезаписи). Эта информация не известна во время компиляции и, следовательно, нет ошибок во время компиляции. Имейте в виду, что хотя векторы и большинство других коллекций C ++ STL можно расширять во время выполнения, они не могут быть расширены с помощью своих обычных операций итераторов (которые в основном служат для перечисления элементов и определения диапазонов).

Функция back_inserter возвращает специальный итератор, который вставляет элементы в конец коллекции. Этот итератор является выходным итератором и имеет очень мало общего с итераторами, которые можно получить с помощью методов begin() и end() вектора. Вы не можете читать из выходного итератора.

0 голосов
/ 08 декабря 2011

Подумайте о простом случае массивов - с указателями на их итераторы. Теперь представьте, что s и v были массивами. Если s имеет 3 элемента и v 0, и вы пытаетесь скопировать s в v, это не сработает. Однако если v имеет 3 элемента, то копия будет работать, перезаписывая текущее содержимое.

Модель итератора в STL является обобщением этого. Действительно, указатели могут быть использованы в качестве итераторов, как и другие объекты (вы можете вызвать copy с указателем на первый элемент массива и указателем на один после конца, и это работает). Поэтому он не работает по той же причине.

back_inserter - итератор, предназначенный именно для этого случая; вместо того, чтобы перемещаться по коллекции, перезаписывая ее текущую позицию, он увеличивает размер коллекции (которая, следовательно, должна, следовательно, быть коллекцией, которая может расти, например вектор) и записывает в новую позицию.

...