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

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

相关文章:

  • 【深度学习新浪潮】以图搜地点是如何实现的?(含大模型方案)
  • 哈尔滨云前沿服务器托管,服务器租用
  • 打板策略实战对比,khQuant回测横评第三弹【AI量化第29篇】
  • 题目 3313: 蓝桥杯2025年第十六届省赛真题-电池分组
  • 云效流水线Flow使用记录
  • 宝塔安装easyswoole框架
  • 思澈科技助力Keep Watch Pilot 1:重新定义智能运动手表体验
  • 精益数据分析(88/126):从营收平衡到规模化扩张——企业增长的最后一道关卡
  • WPF中的图标闪烁功能
  • OpenAI O3惊现算法的自由意识,AGI初现?
  • 【PhysUnits】14 二进制数的标准化表示(standardization.rs)
  • 封装索引列表
  • 四、web安全-行业术语
  • 汽车电子/电气(E/E)架构将朝着区域(分区)式架构方向发展
  • Mac redis下载和安装
  • JavaEE初阶-网络编程
  • javaEE1
  • 从大模型加载到交互:3D Web轻量化引擎HOOPS Communicator如何打造流畅3D体验?
  • Django ToDoWeb 服务
  • 【JavaEE】-- 文件操作和IO
  • 久久建筑网登录入口/亚马逊排名seo
  • 青岛网站建设推进/百度关键词推广费用
  • 哪个软件可以做网站/俄罗斯搜索引擎
  • 阜阳做网站的公司/网络推广大概需要多少钱
  • 宁波公司网站建设定制服务/seo云优化外包
  • 快速建站软件排名/百度seo排名优化教程