поскольку
- они оба являются непрерывными контейнерами памяти;
- Что касается функций, в deque есть почти все, что есть в векторе, но даже больше, поскольку его эффективнее вставлять спереди.
Почему whould кто предпочитает , std::vector
чтобы std::deque
?
std::deque
имеет очень маленький максимальный размер блока (~ 16 байт, если я правильно помню; возможно, 32), и поэтому не очень хорошо работает для реалистичных приложений. Adeque<T>
wheresizeof(T) > 8
(или 16? Это небольшое число) имеет примерно те же характеристики производительности, что и avector<T*>
, где каждый элемент выделяется динамически. Другие реализации имеют разные максимальные размеры блоков, поэтому писать код с относительно одинаковыми характеристиками производительности на разных платформах сложноdeque
.Ответы:
Элементы в
deque
являются не смежными в памяти;vector
элементы гарантированно будут. Так что, если вам нужно взаимодействовать с простой библиотекой C, которой требуются непрерывные массивы, или если вы (очень сильно) заботитесь о пространственной локальности, тогда вы можете предпочестьvector
. Кроме того, поскольку существует некоторая дополнительная бухгалтерия, другиеvector
операции, вероятно, (немного) дороже, чем их эквивалентные операции. С другой стороны, использование многих / больших экземпляровvector
может привести к ненужной фрагментации кучи (замедлению вызововnew
).Кроме того, как указано в другом месте на StackOverflow , здесь есть более интересное обсуждение: http://www.gotw.ca/gotw/054.htm .
источник
Чтобы понять разницу, нужно знать, как
deque
это вообще реализовано. Память распределяется блоками равного размера, и они связаны вместе (как массив или, возможно, вектор).Итак, чтобы найти n-й элемент, вы находите соответствующий блок, а затем получаете доступ к элементу внутри него. Это постоянное время, потому что это всегда ровно 2 поиска, но это все равно больше, чем вектор.
vector
также хорошо работает с API-интерфейсами, которым нужен непрерывный буфер, потому что они либо являются API-интерфейсами C, либо более универсальны с точки зрения возможности принимать указатель и длину. (Таким образом, у вас может быть вектор под ним или обычный массив и вызов API из вашего блока памяти).Где
deque
его самые большие преимущества:Второй из них менее известен, но для очень больших размеров коллекции:
Когда в прошлом я имел дело с большими коллекциями и перешел от непрерывной модели к блочной модели, мы смогли хранить примерно в 5 раз больше коллекции, прежде чем у нас закончилась память в 32-битной системе. Отчасти это связано с тем, что при перераспределении фактически необходимо было сохранить старый блок, а также новый, прежде чем копировать элементы.
Сказав все это, вы можете столкнуться с проблемами
std::deque
в системах, которые используют «оптимистичное» распределение памяти. Хотя его попытки запросить большой размер буфера для перераспределения avector
, вероятно, будут отклонены в какой-то момент с помощью abad_alloc
, оптимистичный характер распределителя, вероятно, всегда будет предоставлять запрос на меньший буфер, запрошенный a,deque
и это может вызвать операционная система, чтобы убить процесс, чтобы попытаться получить некоторую память. То, что он выберет, может оказаться не слишком приятным.Обходными путями в таком случае являются либо установка флагов системного уровня для переопределения оптимистичного распределения (не всегда выполнимо), либо несколько более ручное управление памятью, например, использование вашего собственного распределителя, который проверяет использование памяти, или подобное. Очевидно, не идеально. (Что может ответить на ваш вопрос о предпочтении вектора ...)
источник
Я реализовал как vector, так и deque несколько раз. deque намного сложнее с точки зрения реализации. Это усложнение приводит к увеличению кода и более сложному коду. Таким образом, вы, как правило, увидите, что размер кода значительно снизился, когда вы выбрали deque вместо вектора. Вы также можете столкнуться с небольшим падением скорости, если ваш код использует только то, что выделяется вектором (например, push_back).
Если вам нужна двусторонняя очередь, явным победителем будет deque. Но если вы делаете большую часть своих вставок и стираний на спине, вектор будет явным победителем. Если вы не уверены, объявите свой контейнер с помощью typedef (чтобы было легко переключаться туда и обратно) и измерьте.
источник
vector
.) Я написал реализацию, ссылка на которую приведена ниже в моем ответе . Это может быть так же быстро, как иvector
гораздо более широко применимое (например, при создании быстрой очереди).std::deque
не имеет гарантированной непрерывной памяти - и часто бывает несколько медленнее для индексированного доступа. Двусторонняя очередь обычно реализуется как «список векторов».источник
Согласно http://www.cplusplus.com/reference/stl/deque/ , «в отличие от векторов, deques не гарантируется, что все его элементы находятся в смежных местах хранения, что исключает возможность безопасного доступа с помощью арифметики указателей».
Deques немного сложнее, отчасти потому, что они не обязательно имеют непрерывную структуру памяти. Если вам нужна эта функция, вы не должны использовать двухстороннюю очередь.
(Раньше в моем ответе говорилось об отсутствии стандартизации (из того же источника, что и выше, «deques могут быть реализованы конкретными библиотеками по-разному»), но на самом деле это применимо практически к любому стандартному типу данных библиотеки.)
источник
std::deque
не менее стандартизирован, чемstd::vector
. Я не верю, что требования к сложностиstd::deque
можно удовлетворить с помощью непрерывного хранилища.deque
нельзя удовлетворить при непрерывном хранилище?deque
, а именно, что вставка на концах не должна аннулировать ссылки на существующие элементы. Это требование подразумевает прерывистую память.Двусторонняя очередь - это контейнер последовательности, который позволяет произвольный доступ к своим элементам, но не гарантирует непрерывное хранилище.
источник
Я думаю, что это хорошая идея - проверять работоспособность каждого случая. И принимайте решение, опираясь на эти тесты.
Я бы предпочел,
std::deque
чемstd::vector
в большинстве случаев.источник
vector
. Мы можем сделать вывод, что почему не является следствием. Сказать, что выdeque
по неизвестным причинам предпочитаете результаты неуказанных тестов, не является ответом.Вы бы не предпочли векторной деке в соответствии с этим результатам тестирования (с исходным кодом), .
Конечно, вы должны тестировать в своем приложении / среде, но в итоге:
Еще несколько размышлений и примечание для рассмотрения round_buffer.
источник
С одной стороны, vector довольно часто просто быстрее, чем deque. Если вы на самом деле не нужно все функции deque, используйте вектор.
С другой стороны, иногда вы делаете функции нужно , какой вектор не дает вам, в этом случае вы должны использовать Deque. Например, я призываю любого попытаться переписать этот код без использования двухсторонней очереди и без существенного изменения алгоритма.
источник
push_back
и той же серииpop_back
операций иdeque<int>
всегда, как минимум на 20% быстрее, чемvector<int>
в моих тестах (gcc с O3). Думаю, именно поэтомуdeque
это стандартный выбор для таких вещей, какstd::stack
...Обратите внимание, что векторная память перераспределяется по мере роста массива. Если у вас есть указатели на векторные элементы, они станут недействительными.
Кроме того, если вы удалите элемент, итераторы станут недействительными (но не «for (auto ...)»).
Изменить: изменено 'deque' на 'vector'
источник