Qt开发:智能指针的介绍和使用
文章目录
- 一、QScopedPointer
- 二、QSharedPointer
- 三、QWeakPointer
一、QScopedPointer
1.1 概念
QScopedPointer 是 Qt 提供的独占式智能指针,用于在作用域结束时自动释放对象,避免手动 delete。
主要特点:
- 独占:每个 QScopedPointer 只能管理一个对象,不能被拷贝。
- 自动释放:指针超出作用域时,管理的对象会被自动删除。
- 轻量级:只管理对象生命周期,不维护引用计数。
1.2 常用成员函数
- data():返回内部原始指针
- operator->():访问对象成员
- operator*():解引用对象
- reset(T* ptr = nullptr):替换管理的对象,释放原对象
- take():放弃管理权,不删除对象,返回原始指针
1.3 使用示例
#include <QCoreApplication>
#include <QScopedPointer>
#include <QDebug>class Test {
public:Test() { qDebug() << "Test 构造"; }~Test() { qDebug() << "Test 析构"; }void hello() { qDebug() << "Hello from Test"; }
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建一个 QScopedPointer 管理对象QScopedPointer<Test> ptr(new Test());ptr->hello(); // 访问对象成员(*ptr).hello(); // 解引用访问成员// 替换管理对象ptr.reset(new Test());// 获取内部指针但不删除对象Test* rawPtr = ptr.take();if(rawPtr) {rawPtr->hello();delete rawPtr; // 需要手动删除,因为 take() 放弃了管理权}// ptr 超出作用域时,会自动删除原对象(如果有的话)return a.exec();
}
1.4 初始化方法
直接用构造函数初始化(最常用)
QScopedPointer<Test> ptr(new Test()); // 最直接的方式
- 这种方式最常见,也最安全。
- 指针在 ptr 超出作用域时自动释放。
默认构造 + reset() 初始化
QScopedPointer<Test> ptr; // 空指针
ptr.reset(new Test()); // 初始化对象
- 优点:可以在运行时动态决定管理的对象。
- 注意:reset() 会先删除原有对象(如果有)。
使用已有裸指针 + take() 接管
如果有一个已经存在的裸指针,也可以用 reset() 或构造函数接管:
Test* raw = new Test();
QScopedPointer<Test> ptr(raw); // 接管 raw 的管理
注意:不要重复 delete 原始指针,否则会 double free。
如果需要放弃管理权,可以用 take()
Test* raw2 = ptr.take(); // ptr 不再管理 raw2
结合函数返回值初始化
QScopedPointer<Test> createTest() {return QScopedPointer<Test>(new Test());
}auto ptr = createTest(); // 自动管理对象
二、QSharedPointer
2.1 概念
QSharedPointer 是 Qt 提供的 引用计数智能指针,类似于 C++11 的 std::shared_ptr。
- 多个 QSharedPointer 可以共享同一个对象
- 当最后一个引用被销毁时,对象会自动释放。
- 可以与 QWeakPointer 配合使用,避免循环引用。
特点:
- 自动管理对象生命周期,防止内存泄漏。
- 内部维护 引用计数。
- 可以安全地在多个地方共享同一对象。
2.2 常用成员函数
- data():返回内部原始指针
- operator->():访问对象成员
- operator*():解引用对象
- isNull():判断是否为空
- clear():释放当前管理的对象
- swap():交换两个 QSharedPointer 管理的对象
- useCount():返回当前引用计数
2.3 基本使用示例
#include <QCoreApplication>
#include <QSharedPointer>
#include <QDebug>class Test {
public:Test() { qDebug() << "Test 构造"; }~Test() { qDebug() << "Test 析构"; }void hello() { qDebug() << "Hello from Test"; }
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建 QSharedPointer 管理对象QSharedPointer<Test> ptr1(new Test());qDebug() << "ptr1.useCount() =" << ptr1.useCount();// 拷贝 QSharedPointerQSharedPointer<Test> ptr2 = ptr1;qDebug() << "ptr1.useCount() =" << ptr1.useCount();qDebug() << "ptr2.useCount() =" << ptr2.useCount();// 访问对象ptr1->hello();(*ptr2).hello();// 清空一个指针ptr1.clear();qDebug() << "ptr1 cleared";qDebug() << "ptr2.useCount() =" << ptr2.useCount();// 当最后一个指针超出作用域,Test 对象自动析构return a.exec();
}
为了避免循环引用,可以使用 QWeakPointer:
QSharedPointer<Test> shared(new Test());
QWeakPointer<Test> weak = shared;if (auto ptr = weak.toStrongRef()) {ptr->hello(); // 转换成 QSharedPointer 再使用
}
三、QWeakPointer
3.1 概念
QWeakPointer 是 Qt 提供的 弱引用智能指针,用于与 QSharedPointer 搭配使用。
- 作用:观察 QSharedPointer 管理的对象,但 不增加引用计数。
- 目的:防止循环引用(循环引用会导致对象无法释放)。
特点:
- 不会阻止对象析构。
- 可以通过 toStrongRef() 临时获取 QSharedPointer 使用对象。
- 如果对象已经析构,toStrongRef() 会返回空指针。
3.2 常用成员函数:
- toStrongRef():转换成 QSharedPointer,如果对象还存在则返回有效 QSharedPointer,否则为空
- isNull():判断对象是否已经析构或不存在
- clear():释放对对象的弱引用
3.2 基本使用示例
#include <QCoreApplication>
#include <QSharedPointer>
#include <QWeakPointer>
#include <QDebug>class Test {
public:Test() { qDebug() << "Test 构造"; }~Test() { qDebug() << "Test 析构"; }void hello() { qDebug() << "Hello from Test"; }
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建 QSharedPointer 管理对象QSharedPointer<Test> shared(new Test());// 创建 QWeakPointer 观察 sharedQWeakPointer<Test> weak = shared;qDebug() << "shared.useCount() =" << shared.useCount();qDebug() << "weak.isNull() =" << weak.isNull();// 临时获取 QSharedPointer 使用对象if (auto temp = weak.toStrongRef()) {temp->hello();qDebug() << "temp.useCount() =" << temp.useCount();}// 清空原始 QSharedPointershared.clear();qDebug() << "shared cleared";// 再次尝试获取对象if (auto temp = weak.toStrongRef()) {temp->hello();} else {qDebug() << "对象已被销毁,无法访问";}return a.exec();
}
使用场景:
1. 打破循环引用
- 当对象 A 和对象 B 都持有 QSharedPointer 对方时,会形成循环引用。
- 将其中一个 QSharedPointer 改为 QWeakPointer,即可让对象正常析构。
2. 观察对象生命周期
- QWeakPointer 可以安全地检查对象是否存在,而不会阻止它被析构。
3. 临时访问共享对象
- 通过 toStrongRef() 获取临时 QSharedPointer 安全使用对象。