Почему 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
является лучшим вариантом в отношении производительности только в том случае, если вы воспользуетесь его конкретными свойствами (например, что объекты остаются на месте и что вы можете вставлять/удалять в конце). Однако стоит профилировать две альтернативы.