【QT】Qt智能指针QPointer、QSharedPointer、QWeakPointer、QScopedPointer

QPointer

QPointer can only point to QObject instances. It will be automatically set to nullptr if the pointed to object is destroyed. It is a weak pointer specialized for QObject.
QPointer只能指向QObject实例。如果指向的对象被销毁,它将自动设置为 nullptr。它是一个专门用于QObject的弱指针。

template <typename T>
class QPointer

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

PS:请注意,类T必须继承自QObject,否则将导致编译或链接错误。

QSharedPointer

A reference-counted pointer. The actual object will only be deleted, when all shared pointers are destroyed. Equivalent to std::shared_ptr.
引用计数指针。只有当所有共享指针都被销毁时,实际对象才会被删除。相当于 std::shared_ptr。

template <typename T>
class QSharedPointer

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

PS:QSharedPointer 是线程安全的,因此即使有多个线程同时修改 QSharedPointer 对象也不需要加锁。虽然 QSharedPointer 是线程安全的,但是 QSharedPointer 指向的内存区域可不一定是线程安全的。所以多个线程同时修改 QSharedPointer 指向的数据时还要应该考虑加锁。

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 lock is equivalent to toStrongRef.
可以保存对共享指针的弱引用。它不会阻止对象被破坏,而只是重置。相当于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());

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是一个小型实用程序类,它通过将基于堆栈的内存所有权分配给堆分配(通常称为资源获取即初始化(resource acquisition is initialization:RAII)来大大简化这一过程。

QScopedPointer保证当当前作用域消失时,所指向的对象将被删除。

template <typename T, typename Cleanup>
class QScopedPointer

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
}

Example

class UISvgIcon::Pimpl
{
public:
	Pimpl(const QString &svgPath);
	~Pimpl();
	
public:
	QScopedPointer<QDomDocument> mSvgDoc_;
	QScopedPointer<QSvgRenderer> pSvgRender_;
	QScopedPointer<QPixmap> pPixmap_;
};

UISvgIcon::Pimpl::Pimpl(const QString &svgPath)
{
	mSvgDoc_.reset(new QDomDocument());

	pSvgRender_.reset(new QSvgRenderer(mSvgDoc_->toByteArray()));

	auto tDpi = UPGLUtil::getScreen()->logicalDotsPerInch();

	pPixmap_.reset(new QPixmap(SVGProperty(mSvgDoc_->documentElement(), "svg", "width").toInt() * tDpi,
	                           SVGProperty(mSvgDoc_->documentElement(), "svg", "height").toInt() * tDpi));
}

参考文章

  1. Qt智能指针QPointer、QSharedPointer、QScopedPointer
  2. What is the difference between QPointer, QSharedPointer and QWeakPointer classes in Qt?
### Qt 智能指针概述 Qt 提供了一组智能指针类来帮助开发者更安全地管理动态分配的对象生命周期。这些智能指针可以自动释放不再使用的对象,从而减少内存泄漏的风险[^1]。 以下是几种常见的 Qt 智能指针及其用法: --- ### 一、 `QSharedPointer` `QSharedPointer` 是一种共享所有权的智能指针,类似于 C++ 标准库中的 `std::shared_ptr`。它通过引用计数机制跟踪有多少个 `QSharedPointer` 实例指向同一个对象。当最后一个 `QSharedPointer` 被销毁时,所管理的对象也会被自动删除。 #### 示例代码 ```cpp #include <QSharedPointer> #include <QObject> class MyClass : public QObject { Q_OBJECT public: MyClass() { qDebug("MyClass created"); } ~MyClass() { qDebug("MyClass destroyed"); } }; int main() { QSharedPointer<MyClass> ptr(new MyClass()); // 此处会打印 "MyClass created" } // 当函数结束时,ptr 的析构函数会被调用并释放 MyClass 对象 ``` --- ### 二、 `QWeakPointer` `QWeakPointer` 是一种弱引用智能指针,通常与 `QSharedPointer` 结合使用。它的主要作用是避免循环引用问题。由于不增加引用计数,因此不会阻止对象被销毁[^2]。 #### 示例代码 ```cpp #include <QSharedPointer> #include <QWeakPointer> #include <QDebug> int main() { QSharedPointer<int> strongPtr(new int(42)); QWeakPointer<int> weakPtr = strongPtr.toWeakRef(); if (strongPtr) { qDebug() << *strongPtr; // 输出 42 } strongPtr.clear(); // 手动清除强指针 if (!weakPtr.isExpired()) { qDebug() << weakPtr.toStrongRef().data(); } else { qDebug() << "Object has been deleted"; } } ``` --- ### 三、 `QScopedPointer` `QScopedPointer` 是一种独占所有权的智能指针,适用于仅在一个范围内有效的对象。一旦超出范围,对象就会被自动清理。这种设计非常适合那些不需要多个指针共享同一对象的情况。 #### 示例代码 ```cpp #include <QScopedPointer> #include <QObject> class MyResource { public: MyResource() { qDebug("Resource allocated"); } ~MyResource() { qDebug("Resource deallocated"); } }; void useScopedPointer() { QScopedPointer<MyResource> resource(new MyResource()); // 在此范围内有效 } // 函数结束后,resource 自动释放其管理的对象 ``` --- ### 四、 `QPointer` `QPointer` 是一种特殊的弱指针,专门用于管理继承自 `QObject` 的对象。它可以检测目标对象是否已经被销毁,并在必要时返回空值。 #### 示例代码 ```cpp #include <QObject> #include <QPointer> #include <QDebug> class MyQObject : public QObject { Q_OBJECT public: explicit MyQObject(QObject* parent = nullptr) {} }; int main() { QPointer<MyQObject> obj = new MyQObject; delete obj.data(); // 显式删除对象 if (!obj) { qDebug() << "The object was deleted."; } } ``` --- ### 五、 Qt 智能指针需要注意的事项 尽管 Qt 智能指针提供了许多便利功能,但在实际开发中仍需注意一些潜在陷阱: - **循环引用**:如果两个或更多对象相互持有对方的 `QSharedPointer`,可能会导致它们都无法正常释放。此时应考虑改用 `QWeakPointer` 来打破循环引用关系。 - **原始指针传递风险**:即使使用了智能指针,在某些情况下仍然可能需要手动操作原始指针。务必小心处理这种情况下的资源管理逻辑[^3]。 --- ### 总结 Qt 中的智能指针提供了一个强大的工具集,能够显著简化动态内存管理的任务。每种类型的智能指针都有特定的应用场景和行为特点,合理选择合适的类型对于构建高效且稳定的程序至关重要。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值