Qt: Хранение пользовательского объекта в коллекции по значению - PullRequest
0 голосов
/ 02 июня 2011

Допустим, у меня есть этот класс:

class Bear
{
public:
    Bear ();
    Bear (Bear &other);

    // ... methods

private:
    BearInfo* m_pInfo;
};

Можно ли хранить Bear объекты в QList<Bear> по значению ? Согласно документации:

Внутренне QList<T> представляется в виде массива указателей на элементы типа T. Если T само по себе тип указателя или базовый тип, который не больше указателя, или если T является одним из общих ресурсов Qt классы, то QList<T> сохраняет элементы непосредственно в массиве указателей.

Хотя мой класс состоит только из указателя, он не является типом указателя или базовым типом , поэтому мне кажется, что QList будет хранить указатели (Bear*), чего я не хочу. И поскольку структура BearInfo должна быть изменчивой, я не могу получить Bear из QSharedDataPointer.

Любые предложения, как я могу включить этот класс для хранения по значению в коллекциях Qt?

Ответы [ 3 ]

2 голосов
/ 02 июня 2011

Используйте QVector , документация Qt гласит:

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

  • Для большинства целей QList является правильным классом для использования. Такие операции, как prepend () и insert () обычно выполняются быстрее, чем с QVector, из-за способа, которым QList хранит свои элементы в памяти (подробности см. В разделе Алгоритмическая сложность), а его API на основе индексов более удобен, чем API на основе итераторов QLinkedList. Он также расширяется до меньшего количества кода в вашем исполняемом файле.
  • Если вам нужен реальный связанный список с гарантиями вставки в постоянное время в середине списка и итераторами для элементов, а не индексов, используйте QLinkedList.
  • Если вы хотите, чтобы элементы занимали смежные позиции в памяти, или если ваши элементы больше, чем указатель, и вы хотите избежать дополнительных затрат на их выделение в куче по отдельности во время вставки, тогда используйте QVector.
  • Если вам нужен низкоуровневый массив переменного размера, может быть достаточно QVarLengthArray.
2 голосов
/ 02 июня 2011

Можно ли хранить объекты Bear в QList<Bear> по значению?

Нет. Ваша цитата из документации была правильной: внутренне, QList<T> магазиныуказатели на элементы типа T.

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

Аналогичная проблема с элементами в QList<> - это проблемы с защитой QVariant, которая содержит любой примитивный тип или некоторые другие небольшие типы (например, QDate).Таким образом, вы получаете семантику значений в QVariant, только если ваше значение помещается в примитив или указатель.

Полное сдерживание будет достигнуто, если у вас будет контейнер объектов, таких как QPointer или QSharedPointer экземпляров,которые логически разделяют и отслеживают ссылки на (подсчитанные ссылки) объекты и т. д.

В отличие от STL (с семантикой значений), Qt опирается на контейнеры «указателей на элементы» из-за проблем, когда эти элементыполиморфный (разные размеры в производных классах).(Это довольно часто встречается в объектно-ориентированных системах, поэтому Qt по умолчанию использует семантику указателей.)

Например, в Qt отлично подходит QList<Bear> (реализовано как контейнер указателей на Bearэкземпляры), но std::list<Bear> будет проблематичным, если все экземпляры Bear имеют разный размер (например, если KodiakBear и BlackBear получены из Bear, и вы добавили эти производные экземпляры в класс std::list<Bear>).В этом случае производное состояние будет «очищено» через семантику значения.

2 голосов
/ 02 июня 2011

просто используйте контейнер stl, он доступен везде, даже в QT.

это то, что я делаю. :)

...