C++ Qt 中的 QPointer、QSharedPointer 和 QWeakPointer 类之间有什么区别?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22304118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 00:02:20  来源:igfitidea点击:

What is the difference between QPointer, QSharedPointer and QWeakPointer classes in Qt?

c++qtpointersqsharedpointerqpointer

提问by Nejat

I have read from the Qt documentations about QPointer, QSharedPointerand QWeakPointerclasses. It says:

我从 Qt 文档中阅读了关于QPointer,QSharedPointerQWeakPointerclasses 的内容。它说:

  1. QPointeris a template class that provides guarded pointers to Qt objects and behaves like a normal C++ pointer except that it is automatically set to 0 when the referenced object is destroyed and no "dangling pointers" are produced.

  2. QSharedPointerclass holds a strong reference to a shared pointer.

  3. QWeakPointerclass holds a weak reference to a shared pointer.

  1. QPointer是一个模板类,它提供指向 Qt 对象的受保护指针,其行为类似于普通的 C++ 指针,除了当引用的对象被销毁并且不产生“悬空指针”时它会自动设置为 0。

  2. QSharedPointer类持有对共享指针的强引用。

  3. QWeakPointer类持有对共享指针的弱引用。

My questions is "What is the difference between these classes?". i.e what is the difference between a pointer to an object and a reference to a pointer? Are they all pointers to objects with different mechanisms and behaviors?

我的问题是“这些课程之间有什么区别?”。即指向对象的指针和指向指针的引用有什么区别?它们都是指向具有不同机制和行为的对象的指针吗?

回答by king_nak

QPointer:
QPointercan only point to QObjectinstances. It will be automatically set to nullptrif the pointed to object is destroyed. It is a weak pointer specialized for QObject.

QPointer:
QPointer只能指向QObject实例。nullptr如果指向的对象被销毁,它将自动设置为。它是一个专门用于 的弱指针QObject

Consider this fragment:

考虑这个片段:

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

QSharedPointer
A reference-counted pointer. The actual object will only be deleted, when all shared pointers are destroyed. Equivalent to std::shared_ptr.

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

Note that as long as there is a shared pointer, the object is not deleted!

注意只要有共享指针,对象就不会被删除!

QWeakPointer:
Can hold a weak reference to a shared pointer. It will not prevent the object from being destroyed, and is simply reset. Equivalent to std::weak_ptr, where lockis equivalent to toStrongRef.

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());

This can be used if you need access to an object that is controlled by another module.

如果您需要访问由另一个模块控制的对象,则可以使用此方法。

To use a weak pointer, you must convert it to a QSharedPointer. You should never base a decision on the weak pointer being valid. You can only use data()or isNull()to determine that the pointer is null.

要使用弱指针,您必须将其转换为QSharedPointer. 您永远不应该根据弱指针是否有效来做出决定。您只能使用data()isNull()来确定指针为空。

Generally, to use a weak pointer, you must convert it to a shared pointer since such an operation ensures that the object will survive for as long as you are using it. This is equivalent to "locking" the object for access and is the only correct way of using the object pointed to by a weak pointer.

通常,要使用弱指针,您必须将其转换为共享指针,因为这样的操作可确保对象在您使用它时一直存在。这等效于“锁定”对象以进行访问,并且是使用弱指针指向的对象的唯一正确方法。

QScopedPointer:
This is just a helper class that will delete the referenced object when the pointer goes out of scope. Thus, binds a dynamically allocated object to a variable scope.

QScopedPointer:
这只是一个帮助类,当指针超出范围时将删除引用的对象。因此,将动态分配的对象绑定到变​​量作用域。

You can use this for RAII semantics for locals, e.g.:

您可以将此用于本地人的 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
}

The item will also be deleted in case of an exception

如果出现异常,该项目也将被删除

Another use case can be member variables of an object. Then you don't need to write a destructor for those:

另一个用例可以是对象的成员变量。那么你不需要为那些编写析构函数:

class MyClass {
public:
    MyClass() : myPtr(new int) {}
private:
    QScopedPointer<int> myPtr; // Will be deleted automatically when containing object is deleted
}