学习记录:Qt之QScopedPointer

本文详细介绍了Qt中的QScopedPointer类,如何通过它自动管理动态分配的内存,避免内存泄漏,并展示了如何在不同场景下使用,包括const指针和自定义清理处理。

在学习Qt中看到这样的一个用法:
QScopedPointer app(new QApplication(argc, argv));看了一下帮助文档QScopedPointer的说明,整理记录一下
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction
QScopedPointer 类存储动态申请的指针对象,并且在析构的时候自动释放指针
QScopedPointer guarantees that the object pointed to will get deleted when the current scope disappears. QScopedPointer 确保指针指向的对象能够自动释放

基本用法

不使用QScopedPointer 的常规方法,需要在很多地方手动调用delete,容易遗漏导致内存泄漏等问题
示例:

void myFunction(bool useSubClass)
 {
     MyClass *p = useSubClass ? new MyClass() : new MySubClass;
     QIODevice *device = handsOverOwnership();

     if (m_value > 3) {
         delete p;
         delete device;
         return;
     }

     try {
         process(device);
     }
     catch (...) {
         delete p;
         delete device;
         throw;
     }

     delete p;
     delete device;
 }

使用QScopedPointer 类,程序能简化:

void myFunction(bool useSubClass)
 {
     // assuming that MyClass has a virtual destructor
     QScopedPointer<MyClass> p(useSubClass ? new MyClass() : new MySubClass);
     QScopedPointer<QIODevice> device(handsOverOwnership());

     if (m_value > 3)
         return;

     process(device);
 }

const指针的QScopedPointer 用法

The const qualification on a regular C++ pointer can also be expressed with a QScopedPointer:

  • const QWidget *const p = new QWidget();
    // is equivalent to:
    const QScopedPointer p(new QWidget());

  • QWidget *const p = new QWidget();
    // is equivalent to:
    const QScopedPointer p(new QWidget());

  • const QWidget *p = new QWidget();
    // is equivalent to:
    QScopedPointer p(new QWidget());

自定义cleanup handlers

QScopedPointer’s second template parameter can be used for custom cleanup handlers.
QScopedPointer’s的第二个模板参数可以用于cleanup handlers
The following custom cleanup handlers exist: 已有的cleanup handler

  • QScopedPointerDeleter
    the default, deletes the pointer using delete
    示例:
    // this QScopedPointer deletes its data using the delete[] operator:
    QScopedPointer<int, QScopedPointerArrayDeleter > arrayPointer(new int[42]);
  • QScopedPointerArrayDeleter
    deletes the pointer using delete []. Use this handler for pointers that were allocated with new [].
  • QScopedPointerPodDeleter
    deletes the pointer using free(). Use this handler for pointers that were allocated with malloc().
    示例:
    // this QScopedPointer frees its data using free():
    QScopedPointer<int, QScopedPointerPodDeleter> podPointer(reinterpret_cast<int *>(malloc(42)));
  • QScopedPointerDeleteLater
    deletes a pointer by calling deleteLater() on it. Use this handler for pointers to QObject’s that are actively participating in a QEventLoop.
  • 自定义cleanup handlers
    如果想要使用自己定义的cleanup handlers,只需要其有一个public static函数void cleanup(T *pointer).
    示例:
// this struct calls "myCustomDeallocator" to delete the pointer
 struct ScopedPointerCustomDeleter      //自定义的cleanup handler
 {
     static inline void cleanup(MyCustomClass *pointer)   //需要包含一个cleanup(T *)p)的函数
     {
         myCustomDeallocator(pointer);
     }
 };

 // QScopedPointer using a custom deleter:
 QScopedPointer<MyCustomClass, ScopedPointerCustomDeleter> customPointer(new MyCustomClass); 

前置申明的类使用QScopedPointer

Classes that are forward declared can be used within QScopedPointer
条件是无论何时,QScopedPointer需要cleanup的时候,前置申明的的类的析构函数能够使用
Concretely, this means that all classes containing a QScopedPointer that points to a forward declared class must have non-inline constructors, destructors and assignment operators
示例:
class MyPrivateClass; // forward declare MyPrivateClass

class MyClass
{
private:
QScopedPointer privatePtr; // QScopedPointer to forward declared class

public:
MyClass(); // OK
inline ~MyClass() {} // VIOLATION - Destructor must not be inline

private:
Q_DISABLE_COPY(MyClass)
/* OK - copy constructor and assignment operators are now disabled, so the compiler won’t implicitely generate them. */
};

Qt智能指针--QScopedPointer ⽂章⽬录 概述 前⼀篇⽂章我们详细的介绍了的⽤法,那么,这⾥继续总结Qt的另⼀个智能指针QScopedPointer的⽤法。 QScopedPointer和C++中的智能指针std::unique_ptr其概念是⼀样的,它包装了new操作符在堆上分配的动态对象,能够保证动态创建 的对象在任何时候都可以被正确地删除。但它有更严格的所有权,并且不能转让,⼀旦获取了对象的管理权,你就⽆法再从它那⾥取回来。 也就是说,只要出了作⽤域,指针就会被⾃动删除,因为它的拷贝构造和赋值操作都是私有的,与QObject及其派⽣类风格相同。 QScopedPointer ⾸先我们来看⼀个官⽅⽰例: 没有使⽤智能指针: void myFunction(bool useSubClass) { MyClass *p = useSubClass ? new MyClass() : new MySubClass; QIODevice *device = handsOverOwnership(); if (m_value > 3) { delete p; delete device; return; } try { process(device); } catch (...) { delete p; delete device; throw; } delete p; delete device; } 上⾯的写法,稍有不慎就会导致内存泄露,但是如果使⽤智能指针,就会变得很简单了: void myFunction(bool useSubClass) { QScopedPointer<MyClass> p(useSubClass ? new MyClass() : new MySubClass); QScopedPointer<QIODevice> device(handsOverOwnership()); if (m_value > 3) return; process(device); } 注意:因为拷贝构造和赋值操作私有的,所以不能⽤作容器的元素。 const 限制 C ++指针的const限定也可以⽤QScopedPointer表⽰: const QWidget *const p = new QWidget(); // 等同于: const QScopedPointer<const QWidget> p(new QWidget()); QWidget *const p = new QWidget(); // 等同于: const QScopedPointer<QWidget> p(new QWidget()); const QWidget *p = new QWidget(); // 等同于: QScopedPointer<const QWidget> p(new QWidget()); 考虑⼀种情况 上⾯说到,使⽤QScopedPointer智能指针动态创建的对象,⼀旦出了作⽤域就会 被⾃动释放并置空,那么如果需要函数返回值怎么办 呢? ⽐如下⾯这种情况: QLabel * createLabel() { QScopedPointer<QLabel> pLabel(new QLabel()); // return pLabel.data(); //invalid return pLabel.take(); //valid } int main(int argc, char *argv[]) { QApplication a(argc, argv); QScopedPointer<QLabel> p1(createLabel()); p1->setText("hello"); p1->show(); return a.exec(); } 注意,我们在createLabel()函数中创建label对象并返回时,不能使⽤data(),⽽要使⽤take(); 因为 T *QScopedPointer::data() const返回指向对象的常量指针,QScopedPointer仍拥有对象所有权。 所以通过data()返回过后就被 ⾃动删除了,从⽽导致mian函数中的p1变成了野指针,程序崩溃。 ⽽使⽤T *QScopedPointer::take()也是返回对象指针,但QScopedPointer不再拥有对象所有权,⽽是转移到调⽤这个函数的caller,同 时QScopePointer对象指针置为NULL。 另外还有⼀个函数要注意。 void QScopedPointer::reset(T *other = Q_NULLPTR):delete⽬前指向的对象,调⽤其析构函数,将指针指向另⼀个对象other,所有 权转移到
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值