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

Qt中的智能指针

Qt中的智能指针

Qt中提供了多种智能指针,用于管理自动分配的内存,避免内存泄漏和悬挂指针的问题。以下是Qt中常见的智能指针及其功能和使用场景:

1. QSharedPointer

QSharedPointer 是 Qt 框架中用于管理动态分配对象的智能指针,类似于 C++11 的 std::shared_ptr。它通过引用计数机制实现内存共享和自动释放.官方文档说明:QSharedPointer Class

功能

  • 多个 QSharedPointer 实例可以共享同一个对象。
  • 当最后一个 QSharedPointer 被销毁时,对象会被自动释放。
  • 支持自定义删除器,可用于管理数组或其他特殊资源
#include <QSharedPointer>
class MyClass {};
int main() {QSharedPointer<MyClass> ptr1(new MyClass());QSharedPointer<MyClass> ptr2 = ptr1; // ptr2 和 ptr1 共享同一个对象return 0;
}

注意事项

1.避免循环引用,可以使用 QWeakPointer 来解决。

2.引用计数机制会增加一定的性能开销。

2. QWeakPointer

QWeakPointer 是一个弱引用智能指针,用于解决 QSharedPointer 可能导致的循环引用问题。

  • 功能
    • 不增加引用计数,但可以安全地引用由 QSharedPointer 管理的对象。
    • 当所有 QSharedPointer 被销毁后,QWeakPointer 会自动置空。

检查对象是否仍然有效:

  • 通过 QWeakPointer::toStrongRef() 方法,检查指向的对象是否仍然有效,返回一个新的 QSharedPointer(如果对象仍然存在)或者一个空指针。
#include <QCoreApplication>
#include<QSharedPointer>
#include<QWeakPointer>
#include<QScopedPointer>
#include<QString>
#include<QDebug>class A
{
public:A(int nA,QString strName):m_nA(nA),m_strName(strName){qDebug() << m_strName << "调用 A 构造函数";}~A(){qDebug() << m_strName << "调用 A 析构函数";}int m_nA;QString m_strName;
};int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// Set up code that uses the Qt event loop here.// Call a.quit() or a.exit() to quit the application.// A not very useful example would be including// #include <QTimer>// near the top of the file and calling// QTimer::singleShot(5000, &a, &QCoreApplication::quit);// which quits the application after 5 seconds.// If you do not need a running Qt event loop, remove the call// to a.exec() or use the Non-Qt Plain C++ Application template.QSharedPointer<A> ptr1(new A(10,"ptr1"));qDebug() << "ptr1中的值 = " << ptr1.get()->m_nA;QWeakPointer<A> weakPtr1 = ptr1;if(auto ptr3 = weakPtr1.toStrongRef()){qDebug() << "Object is still alive.";}else{qDebug() << "Object is already destroyed.";}ptr1.clear();if(auto ptr4 = weakPtr1.toStrongRef()){qDebug() << "Object is still alive.";}else{qDebug() << "Object is already destroyed.";}{// 创建一个 QScopedPointer 指向 A对象QScopedPointer<A> ptr5(new A(20,"ptr5"));// 使用 ptr5 时qDebug() << "Inside the scope";} // 离开作用域时 ptr5 会自动释放 A 对象{// 创建一个 QScopedPointer 指向 A对象QScopedPointer<A> ptr6(new A(30,"ptr6"));// 错误:不能复制 QScopedPointer// QScopedPointer<A> ptr7 = ptr6;QScopedPointer<A> ptr7(new A(0,"ptr7"));ptr7.reset(ptr6.take());qDebug() << "ptr7中的值 = " << ptr7.get()->m_nA;} // 离开作用域时 ptr7 会自动释放 A 对象return a.exec();
}

上述代码运行结果:

A 构造函数
ptr1中的值 =  10
Object is still alive.
A 析构函数
Object is already destroyed.

总结:

  • QWeakPointer 是一个轻量级的引用,允许你从 QSharedPointer 中引用对象而不增加引用计数。
  • 使用 QWeakPointer 可以有效避免循环引用问题,同时可以安全地检查对象是否已经被销毁。

3. QScopedPointer

QScopedPointer 是一个自动管理内存的智能指针,它用于在作用域结束时自动删除其所管理的对象。QScopedPointer 是一种简单的自动化内存管理方式,适合用于在某个局部作用域内创建和销毁对象的情况。它类似于标准C++中的 std::unique_ptr,在作用域结束时自动释放资源,防止内存泄漏。

3.1 QScopedPointer 的特点:

  1. 作用域管理QScopedPointer 在离开作用域时会自动销毁它管理的对象,避免内存泄漏。
  2. 不可共享QScopedPointer 不能复制,只能转移所有权,因此适合在一个作用域中管理资源。
  3. 析构自动释放:当 QScopedPointer 被销毁时,它会自动调用所管理对象的析构函数,释放资源。

3.2 基本用法

 {// 创建一个 QScopedPointer 指向 A对象QScopedPointer<A> ptr5(new A(20));// 使用 ptr5 时qDebug() << "Inside the scope";} // 离开作用域时 ptr5 会自动释放 A 对象

代码运行结果:

A 构造函数
Inside the scope
A 析构函数

3.3 使用 QScopedPointer 进行对象管理

QScopedPointer 是用于确保一个对象在离开作用域时自动释放的工具。它通常适用于单一所有权管理的情况。比如,下面的代码展示了在函数内部创建和自动销毁对象:

3.4 不能复制,能移动

QScopedPointer 不允许复制,因为复制会导致多个指针共享同一个对象,从而带来资源管理问题。它只支持转移所有权,即通过 reset() 或通过初始化一个新的 QScopedPointer 进行所有权的转移。

{// 创建一个 QScopedPointer 指向 A对象QScopedPointer<A> ptr6(new A(30,"ptr6"));// 错误:不能复制 QScopedPointer// QScopedPointer<A> ptr7 = ptr6;QScopedPointer<A> ptr7(new A(0,"ptr7"));ptr7.reset(ptr6.take());qDebug() << "ptr7中的值 = " << ptr7.get()->m_nA;} // 离开作用域时 ptr7 会自动释放 A 对象

代码输出:

"ptr6" 调用 A 构造函数
"ptr7" 调用 A 构造函数
"ptr7" 调用 A 析构函数
ptr7中的值 =  30
"ptr6" 调用 A 析构函数

3.5reset()take() 方法

  • reset():重置 QScopedPointer,并释放其当前所管理的对象。如果指针为空,则不会执行任何操作。
  • take():从 QScopedPointer 中“取走”对象,转移所有权,返回原对象指针,并将 QScopedPointer 置为空。
QScopedPointer<MyClass> ptr1(new MyClass());// 使用 reset() 重置 ptr1
ptr1.reset(new MyClass());  // 释放原来的对象,创建一个新对象// 使用 take() 转移所有权
QScopedPointer<MyClass> ptr2(ptr1.take());  // ptr2 现在持有 MyClass 对象

4. QPointer

QPointer 是一个安全指针,专用于 QObject 及其派生类。

  • 功能
    • 当指向的 QObject 对象被销毁时,QPointer 会自动置空。
    • 避免悬挂指针问题。
#include <QPointer>
#include <QLabel>
QLabel *label = new QLabel("Hello, QPointer!");
QPointer<QLabel> pLabel(label);
delete label; // pLabel 会自动置空

5. QScopedArrayPointer

QScopedArrayPointer 是一个用于管理动态分配数组的智能指针。

功能

当超出作用域时,会自动使用 delete[] 释放数组。

不支持复制操作。

#include <QScopedArrayPointer>
void example() {QScopedArrayPointer<int> intArray(new int[10]);for (int i = 0; i < 10; ++i) {intArray[i] = i * 2;}
}

Qt提供了多种智能指针,每种指针都有其特定的用途和优势。根据实际需求选择合适的智能指针可以有效管理内存,避免内存泄漏和悬挂指针问题。

http://www.xdnf.cn/news/9344.html

相关文章:

  • P4155 [SCOI2015] 国旗计划
  • 学者观察 | 区块链、数字身份、隐私保护为数字世界构筑信任基石——信通院云大所何宝宏
  • C++—decltype
  • 突破 APP 推广困局,apptrace 助力高效拉新增长
  • SAAS架构设计2-流程图-用户与租户之间对应关系图
  • scram-sha-256加密
  • 当前固态硬盘价格趋势如何?Kingston FURY Renegade G5 PCIe 5.0 NVMe M.2固态硬盘何时入手最划算?
  • 岛津Sonialvision X-ray X射线高压发生器控制台
  • 【Webtrees 手册】第 8章 - 网站管理员指南
  • 在 C++ 中,当回调函数是类的成员函数时,this指针的指向由调用该成员函数的对象决定
  • SQL进阶之旅 Day 5: 常用函数与表达式
  • 学习日记-day17-5.27
  • 85从零开始学Java之异常处理的新特性
  • SpringBoot-允许跨域配置
  • Linux显示磁盘空间情况——df命令详解与实战
  • Teigha应用——解析CAD文件(DWG格式)Teigha在CAD C#二次开发中的基本应用
  • 13. CSS定位与伪类/伪元素
  • 60.AI流式回答功能前端实现
  • 【Linux】shell脚本的常用命令
  • 2025年机动车授权签字人考试题库及答案
  • Spyglass:项目目录中的报告结构
  • 从SPDY到HTTP/2:网络协议的革新与未来
  • 华为认证中HCIA/HCIP/HCIE是什么等级?怎么考试?
  • 【NLP基础知识系列课程-Tokenizer的前世今生第三课】多模态世界中的 Tokenizer 策略
  • Leetcode 25. K 个一组翻转链表
  • 在 springboot3.x 使用 knife4j 以及常见报错汇总
  • 力扣面试150题--完全二叉树的节点个数
  • 当UI设计师遇上数字孪生:如何用设计思维重构工业流程?
  • 1998-2023年各地级市国内生产总值、地级市GDP数据(市辖区)
  • 依赖注入(DI)/控制反转(IoC) nodejs案例详解