QVector против QList - PullRequest
       8

QVector против QList

67 голосов
/ 06 июля 2011

У меня есть список целых чисел, которые мне нужно перебрать, но массив неадекватен.В чем различия между vectors и lists и что мне нужно знать, прежде чем выбрать тип?

Просто чтобы прояснить ситуацию, я прочитал документы по QT, но это степеньчто я знаю:

QList<T>, QLinkedList<T> и QVector<T> обеспечивают аналогичную функциональность.Вот краткий обзор:

  • Для большинства целей QList - подходящий класс для использования.Его API на основе индексов более удобен, чем QLinkedList's API на основе итераторов, и обычно он быстрее, чем QVector, из-за того, как он хранит свои элементы в памяти.Он также расширяет область кода в вашем исполняемом файле.
  • Если вам нужен реальный связанный список с гарантиями вставки в постоянное время в середине списка и итераторами элементов, а не индексов, используйте QLinkedList.
  • Если вы хотите, чтобы элементы занимали смежные позиции в памяти, используйте QVector.

Ответы [ 5 ]

114 голосов
/ 07 июля 2011

QVector в основном аналогичен std::vector, как можно догадаться из названия.QList ближе к boost::ptr_deque, несмотря на очевидную связь с std::list.Он не хранит объекты напрямую, а хранит указатели на них.Вы получаете все преимущества быстрых вставок на обоих концах, а перераспределения включают в себя перетасовывание указателей вместо конструкторов копирования, но теряют пространственную локальность фактических std::deque или std::vector и получают много выделений кучи.У него есть какое-то решение, чтобы избежать выделения кучи для небольших объектов, восстановления пространственного местоположения, но, насколько я понимаю, это относится только к вещам, меньшим чем int.

QLinkedList аналогично std::list, и имеет все недостатки этого.Вообще говоря, это должен быть ваш последний выбор контейнера.

Библиотека QT сильно поощряет использование QList объектов, поэтому использование их в вашем собственном коде иногда может избежать ненужной скуки.Использование лишней кучи и случайное позиционирование фактических данных могут теоретически повредить в некоторых обстоятельствах, но зачастую это незаметно.Поэтому я бы предложил использовать QList, пока профилирование не изменится на QVector.Если вы ожидаете, что непрерывное выделение будет важным [читай: вы взаимодействуете с кодом, который ожидает T[] вместо QList<T>], что также может быть причиной для запуска с QVector сразу же.


Если вы спрашиваете о контейнерах в целом и просто используете документы QT в качестве ссылки, то приведенная выше информация менее полезна.

std::vector - это массив, размер которого можно изменить,Все элементы хранятся рядом друг с другом, и вы можете быстро получить доступ к отдельным элементам.Недостатком является то, что вставки эффективны только на одном конце.Если вы помещаете что-то в середину или в начале, вам нужно скопировать другие объекты, чтобы освободить место.В биг-ой нотации вставка в конце - это O (1), вставка в любом другом месте - O (N), а произвольный доступ - это O (1).

std::deque аналогичен, но неГарантированные объекты хранятся рядом друг с другом и позволяют вставлять на обоих концах O (1).Это также требует, чтобы меньшие порции памяти были выделены за один раз, что иногда может быть важно.Произвольный доступ - O (1), а вставка в середине - O (N), такая же, как для vector.Пространственная локальность хуже, чем std::vector, но объекты имеют тенденцию к кластеризации, поэтому вы получаете некоторые преимущества.

std::list - это связанный список.Он требует больше всего памяти из трех стандартных последовательных контейнеров, но предлагает быструю вставку в любое место ... при условии, что вы заранее знаете, куда нужно вставить.Он не предлагает произвольный доступ к отдельным элементам, поэтому вы должны выполнить итерацию в O (N).Но когда-то там, фактическая вставка O (1).Самым большим преимуществом std::list является то, что вы можете быстро соединить их вместе ... если вы переместите весь диапазон значений в другое std::list, вся операция будет O (1).Также намного труднее сделать недействительными ссылки в списке, что иногда может быть важно.

Как правило, я предпочитаю std::deque std::vector, если только мне не нужна возможность передавать данные вбиблиотека, которая ожидает необработанный массив.std::vector гарантированно смежный, поэтому &v[0] работает для этой цели.Я не помню, когда в последний раз я использовал std::list, но это было почти наверняка, потому что мне нужна была более надежная гарантия того, что ссылки остаются в силе.

40 голосов
/ 28 апреля 2017

Все изменилось

Мы находимся в Qt 5.8, и все изменилось, поэтому документация.Это дает четкий и другой ответ на этот вопрос:

QVector должно быть вашим выбором по умолчанию.QVector<T> обычно дает лучшую производительность, чем QList<T>, потому что QVector<T> всегда хранит свои элементы последовательно в памяти, где QList<T> будет размещать свои элементы в куче, если sizeof(T) <= sizeof(void*) и T не объявленоQ_MOVABLE_TYPE или Q_PRIMITIVE_TYPE с использованием Q_DECLARE_TYPEINFO.

См. За и против использования QList для объяснения.Однако QList используется во всех API Qt для передачи параметров и для возврата значений.Используйте QList для взаимодействия с этими API.

11 голосов
/ 06 июля 2011

In QVector аналогично std::vector. QLinkedList похож на std::list. QList - это индексный вектор, но положение памяти не гарантируется (например, std::deque).

2 голосов
/ 27 мая 2013

Из QtList doc:

  • QList для использования в большинстве случаев.Для структур с тысячью элементов обеспечивает эффективную вставку посередине и обеспечивает индексированный доступ.prepend() и append() очень быстро, так как память предварительно выделена на обоих концах внутреннего массива.QList<T> - это массив указателей типа T. Если T имеет указатель или тип общего указателя Qt, объект сохраняется непосредственно в массиве

  • QVector, который предпочтителен вслучай большого количества append() или insert() новых элементов с размером, превышающим указатель, поскольку QVector выделяет память для своих элементов в одном выделении кучи.Для QList вставка добавления нового элемента требует выделения памяти нового элемента в куче.Короче говоря, если вы хотите, чтобы элементы занимали смежные позиции в памяти, или если ваши элементы больше, чем указатель, и вы хотите избежать накладных расходов при их выделении в куче по отдельности во время вставки, используйте QVector.

0 голосов
/ 07 июля 2011

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

Например, если вы хотите добавить элемент, новый массивсоздается, все элементы копируются в новый массив, новый элемент добавляется в конец, а старый массив удаляется.И наоборот, чтобы удалить.

Однако QLinkedList работает с указателями.Таким образом, когда создается новый элемент, выделяется только новое пространство памяти и связывается с единственным фрагментом памяти.Поскольку он работает с указателями, он работает быстрее и эффективнее.

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

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