STL - Копирование смесительных контейнеров - PullRequest
2 голосов
/ 06 марта 2011

Я пытаюсь понять алгоритмы STL.

Копия определяется как:

template<class InputIterator, class OutputIterator>
  OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result )

Может ли кто-нибудь объяснить, почему следующее работает, когда векторы и запросы смешаны, но не работает, когда векторы и множества смешаны.*

Я понимаю, что векторы / deque имеют итераторы с произвольным доступом, где в наборе есть двунаправленные итераторы.Я не понимаю, почему компиляция не удается, когда требуются только итераторы ввода / вывода.

PS: Это всего лишь эксперимент, чтобы улучшить мое понимание :)

Ответы [ 3 ]

5 голосов
/ 06 марта 2011

Ассоциативные контейнеры (в простом C ++ 03) - это специальные контейнеры, которые постоянно сортируют свои элементы, обычно реализуемые как красное черное дерево.Чтобы поддерживать инвариант порядка, итераторы set и map предоставляют постоянные ссылки на ключевой объект, и поэтому его нельзя изменить.

В частности, для std::set<T> итератор обычно будет таким, что std::iterator_traits< std::set<T>::iterator >::referenceравен const T&, и поэтому неявное присвоение в операции std::copy завершится неудачей.

Если вы хотите вставить элементы в набор, вы можете использовать итераторы из заголовка <iterator>который будет выполнять insert операций в наборе:

std::copy( v.begin(), v.end(), std::inserter( s, s.end() ) ); // s is the set
5 голосов
/ 06 марта 2011

std::vector и std::deque имеют способ предварительного выделения пространства.std::set нет.Без предварительного выделения пространства попытка разыменования итератора, который вы передаете в copy, приводит к неопределенному поведению.

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

std::copy(myvector.begin(), myvector.end(), std::back_inserter(mydeque));

std::copy(myvector.begin(), myvector.end(), std::inserter(mySet, mySet.end());
0 голосов
/ 06 марта 2011

Это работает для вектора и deque, потому что вы можете выделить место заранее.Для других контейнеров, таких как map, вам нужен адаптер итератора, который сделает это за вас.Посмотрите на insert_iterator, например.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...