qt的智能指针

发布于:2025-06-05 ⋅ 阅读:(24) ⋅ 点赞:(0)

QPointer

QPointer的功能是:当其指向的对象被删除时,它会被自动置空。也就是说,delete一个QPointer,不需要再写一句使其指向nullptr。
QPointer只能指向QObject或其子类对象,否则会出现编译错误或者链接错误。
QPointer的应用场景是,在取得一个QObject对象后,定义一个QPointer指向其地址,那么在这个QObject对象在其他地方被释放后,定义的QPointer也会一并被置空,这样我们就可以通过判断isNull()来判断该QObject对象是否可用,避免使用了已经被删除的QObject。

代码示例:

    QLabel *pLabel_1 = new QLabel(this);
    QPointer<QLabel> pLabel_2 = pLabel_1;
    pLabel_2 .data()->setText("test");
    pLabel_2 ->setText("test_2");        //两种方法均可行
    delete pLabel_1;
    pLabel_1 = nullptr;
    qDebug()<<pLabel_2.isNull();        //此时pLabel_2已经被置空

QScopedPointer

使用QScopedPointer动态创建对象,一旦该对象出了作用域,它就会被自动释放并且置空。这样一来在函数内部需要临时创建的指针变量就可以使用QScopedPointer,不仅省去了不少代码量,更重要的是避免了很多内存泄漏问题。

QSharedPointer


我在工作中使用QSharedPointer最多,因为当我在函数内创建一个临时指针变量,并且需要用它来做返回值时,虽然QScopedPointer在之前的版本中可以用take()来转移指针的所有权,但是在我使用的QT6.2.4版本中已经被废弃,其他的像QScopedPointer::data() 和 QScopedPointer::get() 均是QScopedPointer保留指针所有权,所以不能用QScopedPointer指针来作为返回值。

因此我更乐于用QSharedPointer来创建临时指针变量,这样就算我不用它来作为返回值,在出了作用域之后,其内部引用计数也会下降到0,从而自动释放内存。而当我需要在函数间传递数据时,QSharedPointer会自动计数当前有多少指针指向同一片内存,在其他地方用完后,QSharedPointer也会自动释放内存,实在是太贴心了。

QSharedPointer本身是线程安全的,但是其指向的内存不一定是内存安全的,这句话怎么理解呢?
我的理解是,QSharedPointer的内部引用计数不需要我们手动去在线程间同步,它会自动管理自己的引用计数,因此可以说QSharedPointer是线程安全的,在同一时间可以有多个线程访问;但是QSharedPointer指向的内存资源不一定是线程安全的,在同一时间若是有多个线程一起访问,还是需要加锁来保证线程安全。

至于使用方法,像普通指针一样使用就行,只是定义上稍有区别:

QSharedPointer<QLabel> obj = QSharedPointer<QLabel>(new QLabel());                            //普通定义
QSharedPointer<QLabel> obj = QSharedPointer<QLabel>(new QLabel(), &QObject::deleteLater);    //指定析构函数

QSharedPointer::clear()
该函数执行后删除该QSharedPointer可能对该智能指针指向内存的引用,但是不影响其他智能指针对该内存块的引用,若是最后一个指向该内存块的QSharedPointer执行了clear()函数,那么该内存块将被释放。