• 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,所有权转移到other。

    QScopedArrayPointer

    对应的还有一个指针QScopedArrayPointer,专门用于处理数组,其用法和QScopedPointer是一样的

    官方简单示例:

    void foo()
      {
          QScopedArrayPointer<int> i(new int[10]);
          i[2] = 42;
          ...
          return; // our integer array is now deleted using delete[]
      }

    超出作用域过后会自动调用delete[]删除指针,这里就不展开描述了。

  • 相关阅读:
    4星|《门口的野蛮人2》:美国宝万之争专业户KKR公司的疯狂借债收购史
    3星|《多样性红利》:10年旧书,《群体智慧》的注解版,习题集性质
    4星|《财经》2018年第26期:全国流感疫苗供应不足
    互联网行业的左其盛好评书21本
    华为相关6本书,都不值得读
    3.5星|《产品觉醒》:针对互联网商业和产品的评论与思考,有实践有洞察
    3星|埃森哲《机器与人》:基于人工智能新闻甚至宣传稿的畅想与分析
    3星|《华为终端战略》:华为手机大事记,企业宣传稿风格
    2.5星|《极简企业史》:资料汇编,一大半内容是相关图书简介
    AspNet Core 发布到Linux系统和发布IIS 注意项
  • 原文地址:https://www.cnblogs.com/zzzsj/p/15926647.html
Copyright © 2020-2023  润新知