当前位置: 首页 > news >正文

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 安全使用对象。
http://www.dtcms.com/a/350221.html

相关文章:

  • 君正T31学习(二)- USB烧录
  • 支持指令流水的计算机系统设计与实现
  • mysql绿色版本教程
  • 【python断言插件responses_validator使用】
  • 校园科研自动气象站:藏在校园里的 “科研小站”
  • Nginx零拷贝技术深度解析
  • 【 Python程序员的Ubuntu入门指南】
  • Python二进制、八进制与十六进制高级操作指南:从底层处理到工程实践
  • freqtrade进行回测
  • 关于熵减 - 电力磁力和万有引力
  • list容器的使用
  • 15、IWDG独立看门狗
  • MTK Android 14 通过属性控制系统设置显示双栏或者单栏
  • VUE 的弹出框实现图片预览和视频预览
  • (多线程)线程安全和线程不安全 产生的原因 synchronized关键字 synchronized可重入特性死锁 如何避免死锁 内存可见性
  • React Native核心技术深度解析_Trip Footprints
  • 电商商品管理效率低?MuseDAM 系统如何破解库存混乱难题
  • AR技术:航空维修工具校准的精准革命
  • 【python】if __name__ == ‘__main__‘的作用
  • 正则表达式 —— \s*
  • C语言运行时候出现栈溢出、段错误(Segmentation fault)、异常码解决?
  • 车灯最新测试标准测试设备太阳光模拟器
  • Kafka 在 6 大典型用例的落地实践架构、参数与避坑清单
  • 【Flink】运行模式
  • Rust Async 异步编程(五):async/.await
  • 怎么把iphone文件传输到windows电脑?分场景选方法
  • 【ansible】roles的介绍
  • 【完整源码+数据集+部署教程】化妆品实例分割系统源码和数据集:改进yolo11-DynamicConv
  • 【C#】.net framework 4.8非常久远的框架如何把日期格式/Date(1754548600000)/以及带T的2025-08-07T14:36:40时间格式转为统一的格式输出
  • 并发编程原理与实战(二十六)深入synchronized底层原理实现