QVector
в основном аналогичен std::vector
, как можно догадаться по названию. QList
ближе к boost::ptr_deque
, несмотря на очевидную связь с std::list
. Он не хранит объекты напрямую, а вместо этого хранит указатели на них. Вы получаете все преимущества быстрой вставки на обоих концах, а перераспределение включает перетасовку указателей вместо конструкторов копирования, но теряет пространственную локальность фактического std::deque
or std::vector
и получает много выделения кучи. У него есть некоторые решения, чтобы избежать выделения кучи для небольших объектов, восстанавливая пространственную локальность, но, насколько я понимаю, это применимо только к вещам, меньшим, чем int
.
QLinkedList
аналогичен ему std::list
и имеет все его недостатки. Вообще говоря, это должен быть ваш последний выбор контейнера.
Библиотека QT сильно поддерживает использование QList
объектов, поэтому использование их в собственном коде иногда может избежать ненужной утомительности. Дополнительное использование кучи и случайное расположение фактических данных теоретически может повредить при некоторых обстоятельствах, но часто незаметно. Поэтому я бы предложил использовать, QList
пока профилирование не предложит перейти на QVector
. Если вы ожидаете, что непрерывное распределение будет важным [прочтите: вы взаимодействуете с кодом, который ожидает T[]
вместо a QList<T>
], это также может быть причиной для начала QVector
сразу же.
Если вы спрашиваете о контейнерах в целом и просто использовали документы QT в качестве справки, то приведенная выше информация менее полезна.
An std::vector
- это массив, размер которого можно изменять. Все элементы хранятся рядом друг с другом, и вы можете быстро получить доступ к отдельным элементам. Обратной стороной является то, что вставки эффективны только на одном конце. Если вы поместите что-то посередине или в начале, вам придется скопировать другие объекты, чтобы освободить место. В нотации big-oh вставка в конце - это O (1), вставка где-либо еще - O (N), а произвольный доступ - O (1).
An std::deque
аналогичен, но не гарантирует, что объекты хранятся рядом друг с другом, и позволяет вставлять на обоих концах O (1). Это также требует одновременного выделения меньших фрагментов памяти, что иногда может быть важно. Произвольный доступ - это O (1), а вставка в середине - O (N), как и для a vector
. Пространственная локальность хуже std::vector
, но объекты имеют тенденцию группироваться, так что вы получаете некоторые преимущества.
Это std::list
связанный список. Он требует наибольших затрат памяти из трех стандартных последовательных контейнеров, но предлагает быструю вставку в любом месте ... при условии, что вы заранее знаете, куда вам нужно вставить. Он не предлагает произвольный доступ к отдельным элементам, поэтому вам нужно выполнить итерацию за O (N). Но как только это произойдет, фактическая вставка будет O (1). Самым большим преимуществом std::list
является то, что вы можете быстро их объединить ... если вы переместите весь диапазон значений в другой std::list
, вся операция будет O (1). Также намного сложнее сделать ссылки в списке недействительными, что иногда может быть важно.
Как правило, я предпочитаю это std::deque
делать std::vector
, если мне не нужно передавать данные в библиотеку, которая ожидает необработанный массив. std::vector
гарантируется непрерывность, поэтому &v[0]
работает для этой цели. Я не помню, когда в последний раз использовал a std::list
, но это было почти наверняка потому, что мне требовались более строгие гарантии относительно того, что ссылки остаются в силе.