В чем разница между классами QPointer, QSharedPointer и QWeakPointer в Qt?

Я прочитал из документации Qt о QPointer, QSharedPointer а также QWeakPointer классы. Это говорит:

  1. QPointer это шаблонный класс, который предоставляет защищенные указатели на объекты Qt и ведет себя как обычный указатель C++, за исключением того, что он автоматически устанавливается равным 0, когда ссылочный объект уничтожается и не создаются "висячие указатели".

  2. QSharedPointer Класс содержит строгую ссылку на общий указатель.

  3. QWeakPointer класс содержит слабую ссылку на общий указатель.

Мои вопросы: "В чем разница между этими классами?". т.е. в чем разница между указателем на объект и ссылкой на указатель? Все ли они указатели на объекты с различными механизмами и поведением?

1 ответ

Решение

QPointer:
QPointer могу только указать на QObject экземпляров. Он будет автоматически установлен на nullptr если указанный объект уничтожен. Это слабый указатель, специализированный для QObject,

Рассмотрим этот фрагмент:

QObject *obj = new QObject;
QPointer<QObject> pObj(obj);
delete obj;
Q_ASSERT(pObj.isNull()); // pObj will be nullptr now

QSharedPointer
Указатель с подсчетом ссылок. Фактический объект будет удален только тогда, когда все общие указатели будут уничтожены. Эквивалентно std::shared_ptr,

int *pI = new int;
QSharedPointer<int> pI1(pI);
QSharedPointer<int> pI2 = pI1;
pI1.clear();
// pI2 is still pointing to pI, so it is not deleted
pI2.clear();
// No shared pointers anymore, pI is deleted

Обратите внимание, что пока есть общий указатель, объект не удаляется!

QWeakPointer:
Может содержать слабую ссылку на общий указатель. Это не помешает уничтожению объекта, а просто сбрасывается. Эквивалентно std::weak_ptr, где lock эквивалентно toStrongRef,

int *pI = new int;
QSharedPointer<int> pI1(pI);
QWeakPointer<int> pI2 = pI1;
pI1.clear();
// No shared pointers anymore, pI is deleted
//
// To use the shared pointer, we must "lock" it for use:
QSharedPointer<int> pI2_locked = pI2.toStrongRef();
Q_ASSERT(pI2_locked.isNull());

Это может быть использовано, если вам нужен доступ к объекту, который контролируется другим модулем.

Чтобы использовать слабый указатель, вы должны преобразовать его в QSharedPointer, Вы никогда не должны основывать решение на действии слабого указателя. Вы можете использовать только data() или же isNull() определить, что указатель является нулевым.

Как правило, чтобы использовать слабый указатель, вы должны преобразовать его в общий указатель, поскольку такая операция гарантирует, что объект будет существовать до тех пор, пока вы его используете. Это эквивалентно "блокированию" объекта для доступа и является единственным правильным способом использования объекта, на который указывает слабый указатель.

  • QSharedPointer: std::shared_ptr
  • QWeakPointer: std::weak_ptr
  • QScopedPointer: std::unique_ptr
  • QPointer: нет эквивалента в STL. Обнуляется, когда QObject разрушается.
Другие вопросы по тегам