Ответ 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()
, чтобы определить, что указатель нулевой.
Как правило, чтобы использовать слабый указатель, вы должны преобразовать его в общий указатель, поскольку такая операция гарантирует, что объект будет существовать до тех пор, пока вы его используете. Это эквивалентно "блокированию" объекта для доступа и является единственным правильным способом использования объекта, на который указывает слабый указатель.
QScopedPointer:
Это просто вспомогательный класс, который будет удалять указанный объект, когда указатель выйдет из области видимости. Таким образом, связывает динамически размещенный объект с переменной областью действия.
Вы можете использовать это для семантики RAII для локальных жителей, например:
MyClass *foo() {
QScopedPointer<MyClass> myItem(new MyClass);
// Some logic
if (some condition) {
return nullptr; // myItem will be deleted here
}
return myItem.take(); // Release item from scoped pointer and return it
}
Элемент также будет удален в случае исключения
Другим вариантом использования могут быть переменные-члены объекта. Тогда вам не нужно писать деструктор для них:
class MyClass {
public:
MyClass() : myPtr(new int) {}
private:
QScopedPointer<int> myPtr; // Will be deleted automatically when containing object is deleted
}