QVector против QList
У меня есть список целых чисел, которые мне нужно перебирать, но массив неадекватен. Каковы различия между векторами и списками и есть ли что-нибудь, что мне нужно знать, прежде чем я выберу тип?
просто чтобы быть ясным, я прочитал документы QT, но это степень того, что я знаю:
QList, QLinkedList и QVector обеспечивают аналогичную функциональность. Вот описание:
- для большинства целей QList является правильным классом для использования. Свой API на основе индексов более удобен, чем API на основе итераторов QLinkedList, и обычно он быстрее, чем QVector, из-за того, как он хранит свои элементы в памяти. Он также расширяется до меньшего количества кода в исполняемом файле.
- Если вам нужен реальный связанный список, с гарантиями постоянных временных вставок в середине списка и итераторов к элементам, а не индексам, используйте QLinkedList.
- если вы хотите, чтобы элементы занимали соседние позиции памяти, используйте QVector.
5 ответов:
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 в качестве ссылки, тогда приведенная выше информация менее полезна.
An
std::vector
- это массив, который можно изменить. Все элементы хранятся рядом друг с другом, и вы можете быстро получить доступ к отдельным элементам. Недостатком является то, что вставки эффективны только на одном конце. Если вы положили что-то в середине или в начале, вы должны скопировать другие объекты, чтобы освободить место. В нотации big-oh вставка в конце - O(1), вставка в любом другом месте-O(N), а произвольный доступ-O(1).An
std::deque
аналогично, но не гарантирует, что объекты хранятся рядом друг с другом, и позволяет вставке на обоих концах быть O(1). Это также требует выделения меньших кусков памяти за один раз, что иногда может быть важно. Произвольный доступ-O(1), а вставка в середине-O (N), то же самое, что и для Avector
. Пространственная локальность хуже, чемstd::vector
, но объекты, как правило, кластеризуются, поэтому вы получаете некоторые выгоды.An
std::list
- это связанный список. Он требует наибольших затрат памяти из трех стандартных последовательных контейнеров, но предлагает быструю вставку в любом месте... при условии, что вы заранее знаете, где вам нужно вставить. Он не предлагает произвольный доступ к отдельным элементам, поэтому вам нужно выполнить итерацию в O(N). Но как только там, фактическая вставка O(1). Самое большое преимущество дляstd::list
это то, что вы можете соединить их вместе быстро... если вы переместите весь спектр значений разныеstd::list
, вся операция O (1). Также гораздо сложнее аннулировать ссылки в списке, что иногда может быть важно.как правило, я предпочитаю
std::deque
доstd::vector
, если мне не нужно передавать данные в библиотеку, которая ожидает необработанный массив.std::vector
гарантируется непрерывность, поэтому&v[0]
работает для этой цели. Я не помню, когда в последний раз я использовалstd::list
, но это было почти наверняка, потому что мне нужна была более сильная гарантия ссылки остаются действительными.
что изменилось
мы сейчас в Qt 5.8 и все изменилось, поэтому документация. Это дает ясный и другой ответ на этот вопрос:
QVector должен быть вашим первым выбором по умолчанию. QVector обычно дайте лучшую производительность, чем QList, потому что QVector всегда сохраняет свои элементы последовательно в памяти, где QList будет выделять его элементы в куче, если sizeof (T)
см. плюсы и минусы использования QList для объяснение. Однако, QList используется на протяжении интервала QT API для прохождения параметры и для возвращаемых значений. Используйте QList для взаимодействия с ними Апис.
на
QVector
похож наstd::vector
.QLinkedList
похож наstd::list
.QList
- это вектор на основе индекса, но позиция памяти не гарантируется (напримерstd::deque
).
из qtlist doc:
QList, который будет использоваться в большинстве случаев. Для структур с тысячью элементов обеспечивает эффективную вставку в середине и обеспечивает индексированный доступ.
prepend()
иappend()
очень быстро, так как память выделена на обоих концах внутреннего массива.QList<T>
является массивом указателя типа T. Если T имеет указатель или Qt shared-like тип указателя, объект хранится непосредственно в массиве
QVector
предпочитает в дело многоappend()
илиinsert()
новых элементов с размером больше указателя, так какQVector
выделяет память для своих элементов в одной куче. ИбоQList
, вставка добавления нового элемента требует выделения памяти нового элемента в куче. Короче говоря, если вы хотите, чтобы элементы занимали соседние позиции памяти, или если ваши элементы больше указателя, и вы хотите избежать накладных расходов на выделение их в куче по отдельности во время вставки, то используйтеQVector
.
QVector похож на массив, который может изменять размер (увеличивать или уменьшать), но он поставляется с тяжелыми транзакциями и вычислениями и временем.
например, если вы хотите добавить элемент, создается новый массив, все элементы копируются в новый массив, новый элемент добавляется в конец, а старый массив удаляется. И наоборот, чтобы удалить, а также.
однако, QLinkedList работает с указателями. Поэтому при создании нового элемента выделяется только новое пространство памяти и связывается с ним единственный кусочек памяти. Поскольку он работает с указателями, это быстрее и эффективнее.
Если у вас есть список элементов, которые вы не ожидаете сильно изменить размер, QVector, вероятно, хорош, но обычно QLinkedList используется для большинства целей.