Почему я предпочитаю использовать vector для deque

С

  1. они оба являются смежными контейнерами памяти;
  2. feature wise, deque имеет почти все, что вектор имеет, но больше, так как он более эффективен для вставки спереди.

почему кто-нибудь предпочитает std::vector до std::deque?

9 ответов


элементов deque are не непрерывен в памяти; vector элементы гарантированно будут. Поэтому, если вам нужно взаимодействовать с простой библиотекой C, которая нуждается в смежных массивах, или если вы заботитесь (много) о пространственной локальности, то вы можете предпочесть vector. Кроме того, поскольку существует некоторая дополнительная бухгалтерия, другие ops, вероятно (немного) дороже, чем их эквивалент vector операции. С другой стороны, используя много / больших экземпляров vector может привести к ненужная фрагментация кучи (замедление вызовов new).

также, как указано в другом месте на StackOverflow, здесь больше хорошего обсуждения:http://www.gotw.ca/gotw/054.htm .


чтобы узнать разницу, нужно знать, как deque обычно реализуется. Память выделяется в блоках равных размеров, и они скованы вместе (как массив или, возможно, вектор).

таким образом, чтобы найти n-й элемент, вы найдете соответствующий блок, а затем получите доступ к элементу внутри него. Это постоянное время, потому что это всегда ровно 2 поиска, но это все еще больше, чем вектор.

vector также хорошо работает с API, которые хотят непрерывный буфер потому что они либо C API, либо более универсальны в том, что могут принимать указатель и длину. (Таким образом, вы можете иметь вектор под или регулярный массив и вызывать API из блока памяти).

здесь deque имеет свои большие преимущества:

  1. при росте или сокращении коллекции с обоих концов
  2. когда вы имеете дело с очень большими размерами коллекции.
  3. при работе с bools, и вы действительно хотите bools, а чем bitset.

второй из них менее известен, но для очень больших размеров коллекции:

  1. стоимость перераспределения велика
  2. накладные расходы, связанные с поиском смежного блока памяти, ограничительны, поэтому вы можете быстрее запускать память.

когда я имел дело с большими коллекциями в прошлом и перешел от смежной модели к блочной модели, мы смогли сохранить примерно в 5 раз больше коллекции до того, как у нас закончилась память в 32-битной системе. Отчасти это связано с тем, что при повторном выделении ему действительно нужно было сохранить старый блок, а также Новый, прежде чем он скопировал элементы.

сказав Все это, вы можете попасть в беду с std::deque в системах, использующих "оптимистичное" распределение памяти. В то время как его попытки запросить большой размер буфера для перераспределения vector вероятно получить отказ в какой-то момент с bad_alloc, оптимизм распределитель, вероятно, всегда будет предоставлять запрос для меньшего буфера, запрошенного deque и это, вероятно, заставит операционную систему убить процесс, чтобы попытаться получить некоторую память. Какой бы он ни выбрал, он может оказаться не слишком приятным.

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


я реализовал как вектор, так и deque несколько раз. deque значительно сложнее с точки зрения реализации. Это усложнение переводится в более сложный код. Таким образом, вы обычно увидите хит размера кода при выборе deque над вектором. Вы также можете испытать небольшую скорость, если ваш код использует только то, что вектор превосходит (т. е. push_back).

Если вам нужна двойная очередь, deque является явным победителем. Но если вы делаете большинство из ваших вставок и стираний на задней панели вектор будет явным победителем. Когда вы не уверены, объявите свой контейнер с typedef (так что легко переключаться туда и обратно) и измерьте.


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


согласно http://www.cplusplus.com/reference/stl/deque/, " в отличие от векторов, deques не гарантируется наличие всех его элементов в смежных местах хранения, что исключает возможность безопасного доступа через арифметику указателей."

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

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


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


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

Я бы предпочел std::deque чем std::vector в большинстве случаев.


вы не желавших предпочитаю вектор к deque согласно эти результаты теста (с источником).

конечно, вы должны протестировать в своем приложении / среде, но вкратце:

  • push_back в основном одинакова для всех
  • insert, erase в deque намного быстрее, чем list и незначительно быстрее, чем vector

еще несколько размышлений и примечание для рассмотрения circular_buffer.


с одной стороны, вектор довольно часто просто быстрее, чем дека. Если вы на самом деле нужно все функции deque, используйте вектор.

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