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
的特点:
- 作用域管理:
QScopedPointer
在离开作用域时会自动销毁它管理的对象,避免内存泄漏。 - 不可共享:
QScopedPointer
不能复制,只能转移所有权,因此适合在一个作用域中管理资源。 - 析构自动释放:当
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提供了多种智能指针,每种指针都有其特定的用途和优势。根据实际需求选择合适的智能指针可以有效管理内存,避免内存泄漏和悬挂指针问题。