it编程 > 编程语言 > C/C++

Qt 智能指针的具体使用

51人参与 2025-03-16 C/C++

qscopedpointer

qscopedpointer 是 qt 提供的一个智能指针,主要用于简化资源管理,防止内存泄漏和悬挂指针问题。它属于 qt 的内存管理工具,能够自动处理对象的生命周期,确保对象在超出作用域时被销毁。qscopedpointer 是基于 c++11 标准中的 std::unique_ptr 实现的,但它具有 qt 的特点,通常用于局部对象的管理。

1. 自动删除对象

qscopedpointer 最常见的用法是在函数或局部作用域内管理动态分配的对象。在作用域结束时,qscopedpointer 自动销毁对象,无需显式调用 delete

#include <qscopedpointer>
#include <qdebug>

class myclass {
public:
    myclass() { qdebug() << "myclass constructed"; }
    ~myclass() { qdebug() << "myclass destructed"; }
};

void testscopedpointer() {
    qscopedpointer<myclass> ptr(new myclass);
    // 当函数返回时,ptr 超出作用域,对象会被自动销毁
} // 在这里,myclass 对象会被自动删除

2. 转移所有权

qscopedpointer 不支持复制操作,但可以通过 reset() 或构造函数转移所有权。这样,qscopedpointer 可以在不同的作用域之间传递资源。

#include <qscopedpointer>
#include <qdebug>

class myclass {
public:
    myclass() { qdebug() << "myclass constructed"; }
    ~myclass() { qdebug() << "myclass destructed"; }
};

void transferownership() {
    qscopedpointer<myclass> ptr1(new myclass);
    // 将所有权从 ptr1 转移到 ptr2
    qscopedpointer<myclass> ptr2(ptr1.take());
    // 现在 ptr1 不再拥有 myclass 对象,ptr2 拥有它

    // ptr1 不再指向对象,但对象仍然存在,由 ptr2 管理
} // 在这里,ptr2 超出作用域时,myclass 对象会被自动删除

3. 管理私有数据

在 qt 的许多类中,私有数据(通常是一个包含实现细节的类)被封装在一个 qscopedpointer 中。这样可以确保私有数据在类的析构函数中自动释放,同时保持代码的简洁性和安全性。

示例:qfile 类

class qfileprivate : public qiodeviceprivate {
    // 私有数据成员
};

class qfile : public qiodevice {
public:
    qfile();
    ~qfile();

private:
    qscopedpointer<qfileprivate> d_ptr;
};

在这个例子中,qfile 类使用 qscopedpointer 来管理 qfileprivate 对象。当 qfile 对象析构时,qscopedpointer 会自动删除 qfileprivate 对象,确保内存被释放。

qsharedpointer

qsharedpointer 是通过引用计数来管理对象的生命周期的,多个 qsharedpointer 对象可以共享同一个资源。每当 qsharedpointer 的拷贝构造或赋值操作发生时,引用计数会增加,而当一个 qsharedpointer 被销毁时,引用计数会减少。当引用计数降到 0 时,所指向的对象会自动被删除。

#include <qsharedpointer>
#include <qdebug>

class myclass {
public:
    void print() { qdebug() << "hello from myclass!"; }
};

int main() {
    // 创建 qsharedpointer 对象,管理 myclass 对象的生命周期
    qsharedpointer<myclass> ptr1(new myclass);

    // 创建另外一个 qsharedpointer,并共享 ptr1 所管理的对象
    qsharedpointer<myclass> ptr2 = ptr1;

    // 使用 ptr1 和 ptr2 都能访问同一个对象
    ptr1->print();
    ptr2->print();

    // 不需要手动释放内存,当最后一个 qsharedpointer 被销毁时,myclass 对象会自动删除
    return 0;
}

关键特性

注意事项

qweakpointer

qweakpointer 是 qsharedpointer 的一种补充,它本身不拥有对象的所有权。qweakpointer 仅在 qsharedpointer 的引用计数为非零时提供访问该对象的能力,但不会阻止对象的销毁。换句话说,qweakpointer 允许你引用一个对象而不会使得该对象无法销毁。

qweakpointer 的主要特点:

qweakpointer 和 qsharedpointer 的配合

qweakpointer 通常与 qsharedpointer 一起使用,用于避免循环引用。在有些情况下,两个对象会互相引用,导致它们的引用计数始终不为零,进而导致内存泄漏。qweakpointer 可以打破这个循环引用链,它允许对象 a 持有对象 b 的 qweakpointer,而对象 b 可以持有对象 a 的 qsharedpointer,从而确保对象 a 和 b 的生命周期由 qsharedpointer 管理。

qweakpointer 的常见用法

下面是一个使用 qweakpointer 的具体示例:

class b;  // forward declaration

class a {
public:
    qsharedpointer<b> b;  // b的共享指针
};

class b {
public:
    qweakpointer<a> a;  // a的弱引用
};

int main() {
    qsharedpointer<a> a(new a);  // 创建a对象
    qsharedpointer<b> b(new b);  // 创建b对象

    a->b = b;  // a持有b的共享指针
    b->a = a;  // b持有a的弱引用

    return 0;  // 程序退出时,a和b会被自动销毁,避免内存泄漏
}

注意事项

使用qweakpointer时候,一定要使用isnull判断一下 资源是否释放

qsharedpointer<myclass> shared(new myclass(20));
qweakpointer<myclass> weak(shared);

qdebug() << "shared pointer value:" << shared->getvalue();
qdebug() << "weak pointer value:" << weak.data()->getvalue();

shared.clear(); // 删除 shared 指向的对象
// 此时,myclass 对象的引用计数为 0,将被自动删除,而此时 qweakpointer 对象 weak 也为 null。

if (weak.isnull()) {  // 判断 weak 是否为 null
	qdebug() << "weak pointer is null - object has been deleted"; // 执行
}
else {
	qdebug() << "weak pointer is not null - object still exists";
}

qpointer

qpointer 是一个用于指向 qt 对象(例如 qobject 的子类)的模板类,它会自动管理对象的生命周期。当一个 qobject 被销毁时,qpointer 会将其指针设为 nullptr,这使得程序能够检测到所指向的对象已经被删除,从而避免访问已删除的对象,避免悬空指针问题。qpointer 只能用来管理 qobject 或其子类的对象。如果你需要管理其他类型的对象,可以考虑使用其他智能指针,如 std::shared_ptr 或 std::unique_ptr

#include <qpointer>
#include <qpushbutton>
#include <qvboxlayout>
#include <qwidget>
#include <qdebug>

int main(int argc, char *argv[]) {
    qcoreapplication a(argc, argv);

    qwidget window;
    qvboxlayout *layout = new qvboxlayout(&window);

    qpushbutton *button = new qpushbutton("click me");
    qpointer<qpushbutton> pbutton(button);

    layout->addwidget(button);
    window.show();

    qobject::connect(button, &qpushbutton::clicked, [&] {
        if (pbutton) {
            qdebug() << "button exists, text:" << pbutton->text();
        } else {
            qdebug() << "button has been deleted";
        }
    });

    // 模拟按钮删除
    qobject::connect(button, &qpushbutton::clicked, [&] {
        delete button;
    });

    return a.exec();
}

到此这篇关于qt 智能指针的具体使用的文章就介绍到这了,更多相关qt 智能指针内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网! 

(0)

您想发表意见!!点此发布评论

推荐阅读

Qt把文件夹从A移动到B的实现示例

03-16

QT移植到RK3568开发板的方法步骤

03-16

C++数组去重十种方法

03-16

C++记录程序运行时间的四种方法

03-17

C/C++随机数生成的五种方法

03-17

VSCode中C/C++编码乱码问题的两种解决方法

03-17

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论