Почему std::vector настолько популярнее, чем std:: deque?

Возможный дубликат:
Почему я предпочитаю использовать вектор для deque

Мне любопытно, почему std::vector гораздо более популярен, чем std::deque. Deque почти так же эффективен в поиске, более эффективен при вставке (без vector:: reserve) и позволяет вставлять/удалять спереди.

Трава Саттер однажды рекомендовала если вы хотите использовать вектор, просто предпочитаете deque (я перефразирую). Однако в недавнем разговоре о Написание Modern С++ он настоятельно рекомендует думать о std::vector как контейнере по умолчанию. Согласно GOTW, который я связал ранее, даже стандарт имеет аналогичную формулировку.

Есть ли причина такого несоответствия? Это просто, что vector является более простым и более известным, или существует техническая причина? Или это, что vector - просто более холодное имя..?

Ответ 1

Я не могу говорить ни для кого другого, но я могу для себя.

Когда я впервые прочитал о std::deque, я подумал, что достаточно прохладно, что некоторое время я рассматривал его не только как контейнер по умолчанию, но как почти единственный контейнер, который я использовал.

Тогда кто-то спросил о том, почему, и я подробно изложил его достоинства и почему он был лучшим контейнером для использования практически для всего и как он был гораздо более универсальным, чем std::vector.

К счастью, парень, который допрашивал мое решение по этому поводу, был достаточно убедителен, что я провел некоторое тестирование. Тестирование показало, что почти каждый случай std::deque был медленнее, чем std::vector - часто с существенным фактором (например, около 2). Фактически, кода, который я написал с помощью std::deque, просто замена std::deque на std::vector дала ускорение во всех случаях, кроме нескольких случаев.

Я использовал std::deque в нескольких случаях с тех пор, но определенно не рассматриваю его как значение по умолчанию. Простой факт состоит в том, что в обычной реализации это заметно медленнее, чем std::vector для большинства целей.

Я должен добавить, однако, что я уверен, что при правильной реализации он практически эквивалентен std::vector практически во всех случаях. Большинство из них используют представление, которое, несомненно, имеет большое значение с точки зрения асимптотики, но не так замечательно (для многих целей) не работает в реальном мире.

Ответ 2

std::vector очень хорошо понятен, прост и совместим с C (как с точки зрения макета памяти, так и с точки зрения использования указателей в качестве итераторов).

Для некоторых операций он также более эффективен, чем std::deque. Одним из примеров является доступ к элементам по индексу.

Для данной задачи имеет смысл использовать простейший контейнер, который хорошо выполняет работу. Во многих случаях самый простой контейнер - std::vector.

Ответ 3

Помимо std::vector, который является наиболее известным классом контейнера, он также имеет несколько преимуществ перед std::deque, а именно:

  • Типичный std::deque требует дополнительной косвенности для доступа к элам, в отличие от, как в случае std::vector.
  • Итераторы в случае std::deque должны быть интеллектуальными указателями, а не указателями, как в случае std::vector.
  • Элементы std::vector гарантируют, что они будут непрерывными и, следовательно, совместимы с функциями c-стиля, которые принимают массивы в качестве параметров.
  • std::deque не обеспечивают поддержки для контроля емкости и момента перераспределения.

В частности, примечателен последний пункт.

Ответ 4

Люди используют std::vector по std:: deque по простой причине. Они взаимодействуют с большим количеством библиотек C и имеют функции с параметрами, для которых требуется указатель на непрерывное хранилище, которое std:: deque не имеет ( не можем) гарантировать.

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

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

Ответ 5

Структура std::deque немного сложнее, что делает наивную итерацию довольно дорогой, чем std::vector. Вставки в std::vector с его перераспределением, как правило, не являются большой проблемой, особенно при использовании reserve() и только добавлении к концу. Кроме того, легче понять правила недействительности для std::vector, хотя на самом деле преимущество std::deque заключается в том, что объекты остаются включенными при вставке/удалении только с обоих концов (обратите внимание, что итераторы std::deque становятся недействительными при каждой вставке, независимо от где происходит вставка). Еще один плюс для std:vector - это гарантия того, что значения смежны в памяти, что приводит к меньшему количеству выделения памяти.

Думаю, я бы рекомендовал использовать алгоритмы std::deque, которые были последовательно оптимизированы для использования сегментированных последовательностей (я не знаю, что любая стандартная библиотека С++ делает эту оптимизацию), и пользователи последовательно обращаются к последовательностям с использованием алгоритмов (насколько я может сказать, лишь небольшая часть пользователей рассматривает возможность использования алгоритмов). В противном случае я бы заподозрил, что std::deque является лучшим вариантом в отношении производительности только в том случае, если вы воспользуетесь его конкретными свойствами (например, что объекты остаются на месте и что вы можете вставлять/удалять в конце). Однако стоит профилировать две альтернативы.