Qt智能指针--QScopedPointer

参考原文链接:https://blog.csdn.net/luoyayun361/article/details/90228638

概述
前一篇文章我们详细的介绍了QPointer的用法,那么,这里继续总结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[]删除指针,这里就不展开描述了。
 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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,所有 权转移到
Qt中的智能指针主要有三种:QSharedPointer、QWeakPointer和QScopedPointer。它们都是用来管理动态分配的对象的指针,并且能够自动释放内存,避免内存泄漏。 1. QSharedPointer QSharedPointer是一个线程安全的智能指针,它允许多个指针共享同一个对象,并且能够在最后一个指针离开作用域时自动释放对象。以下是一个简单的示例: ```cpp QSharedPointer<QString> ptr1(new QString("Hello")); QSharedPointer<QString> ptr2 = ptr1; QSharedPointer<QString> ptr3 = ptr2; qDebug() << *ptr1; // 输出"Hello" qDebug() << *ptr2; // 输出"Hello" qDebug() << *ptr3; // 输出"Hello" ``` 2. QWeakPointer QWeakPointer是一个弱引用智能指针,它可以引用由QSharedPointer管理的对象,但不会增加对象的引用计数。当最后一个QSharedPointer离开作用域时,如果没有其他QSharedPointer引用该对象,则该对象被自动释放。以下是一个简单的示例: ```cpp QSharedPointer<QString> ptr1(new QString("Hello")); QWeakPointer<QString> weakPtr1 = ptr1; QWeakPointer<QString> weakPtr2 = weakPtr1; qDebug() << weakPtr1.data(); // 输出"Hello" qDebug() << weakPtr2.data(); // 输出"Hello" ptr1.clear(); qDebug() << weakPtr1.data(); // 输出nullptr qDebug() << weakPtr2.data(); // 输出nullptr ``` 3. QScopedPointer QScopedPointer是一个非共享的智能指针,它在离开作用域时自动释放对象。它不能被复制或共享,因此可以避免由于多个指针共享一个对象而引起的问题。以下是一个简单的示例: ```cpp QScopedPointer<QString> ptr(new QString("Hello")); qDebug() << *ptr; // 输出"Hello" ``` 以上是Qt中三种智能指针的详细介绍及代码示例。使用智能指针可以避免内存泄漏和悬空指针等问题,提高代码的健壮性和可靠性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值