В чем разница между классами QPointer, QSharedPointer и QWeakPointer в Qt?
Я прочитал из документации Qt о QPointer
, QSharedPointer
а также QWeakPointer
классы. Это говорит:
QPointer
это шаблонный класс, который предоставляет защищенные указатели на объекты Qt и ведет себя как обычный указатель C++, за исключением того, что он автоматически устанавливается равным 0, когда ссылочный объект уничтожается и не создаются "висячие указатели".QSharedPointer
Класс содержит строгую ссылку на общий указатель.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 разрушается.