Qt 智能指针QScopedPoint用法小结

 更新时间:2024年01月19日 15:20:18   作者:FreeLikeTheWind  
智能指针是C++11引入的一种指针封装类型,用于自动管理动态分配的内存,本文主要介绍了Qt 智能指针QScopedPoint用法小结,感兴趣的可以了解一下

1. 智能指针是什么

智能指针是C++11引入的一种指针封装类型,用于自动管理动态分配的内存。智能指针的目的是解决传统裸指针带来的内存泄漏、悬挂指针等问题,并使代码更安全、更易读。

2. 智能指针有什么用

1.自动管理内存,避免内存泄漏和悬挂指针问题;
2.简化代码,减少异常处理和资源管理的复杂性;
3.提高代码可读性和可维护性;
4.帮助实现RAII(资源获取即初始化)原则,更好地管理资源。

3. 智能指针和普通指针区别

智能指针和普通指针的主要区别在于内存管理方式。普通指针(裸指针)直接使用内存地址,需要手动申请和释放内存,容易导致内存泄漏和悬挂指针等问题。而智能指针封装了内存地址,通过自动管理内存的方式避免了这些问题。

智能指针内部维护了一个引用计数器,当一个智能指针被创建或拷贝时,计数器加1;当一个智能指针被销毁或重置时,计数器减1。当计数器减至0时,智能指针会自动释放其所指向的内存。这种方式称为“所有权”(ownership)模型,智能指针具有其内存的所有权,避免了普通指针中的多个指针指向同一内存地址的情况。

另外,智能指针还提供了一些有用的成员函数,如reset()、release()等,可以更方便地进行内存管理。同时,智能指针的类型也不同,如std::unique_ptr表示独占所有权的智能指针,std::shared_ptr表示共享所有权的智能指针,std::weak_ptr表示观察智能指针等。

4. QScopedPoint介绍

QScopedPointer类用于存储一个指向动态分配的对象的指针,并在对象销毁时自动删除它。

手动管理堆分配的对象是困难且容易出错的。常见的后果是代码内存泄漏,难以维护。QScopedPointer是一个小工具类,通过将基于堆栈的内存所有权分配给堆分配,一般称资源获取即初始化(RAII),从而大大简化了这一点。

QScopedPointer保证当当前作用域消失时,所指向的对象将被删除。

当使用QScopedPointer时,可以确保在函数退出时,所分配的对象会被自动删除,从而避免了内存泄漏。这使得代码更简洁、更安全,减少了内存泄漏和代码错误的风险。
比如:一般我们自行new在堆中创建对象时,需手动管理内存,如下:

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)
  {
      // 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修饰,普通指针与智能指针的对比:

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());

5. QScopedPoint用法

首先包含头文件

#include <QScopedPointer>
 
QScopedPointer<int> pInt(new int(99));
    qDebug().noquote() << "*pInt :" << *pInt << *pInt.data(); // 99 99

使用很简单。

6. take()和data()方法区别

QScopedPointer 有两个重要的方法:take() 和 data()。

take() 方法:

  • take() 是一个成员函数,它允许你获取 QScopedPointer 所指向的对象,并将 QScopedPointer 设置为 null。这意味着一旦调用了 take(),QScopedPointer 将不再拥有该对象,并且不再负责其生命周期。
  • 这个方法通常用于在多线程环境中安全地传递对象,或者在知道对象生命周期的情况下安全地获取对象。

data() 方法:

  • data() 返回一个指向所持有对象的指针。这个方法主要用于访问或修改所指向的对象。
  • 注意,尽管 data() 返回一个指针,但这个指针的生命周期依赖于 QScopedPointer 的生命周期。如果 QScopedPointer 被销毁,那么这个指针将变得无效。

使用注意事项:

  • 使用 take() 时要特别小心,确保在 take() 之后,不会意外地使用 QScopedPointer,因为这样可能会导致未定义的行为。
  • 使用 data() 时,要确保在 QScopedPointer 的生命周期内使用返回的指针,否则可能会导致悬挂指针或其他问题。
#include <QScopedPointer>  
  
class MyClass {  
public:  
    MyClass() {  
        // 初始化操作  
    }  
    ~MyClass() {  
        // 清理操作  
    }  
    void show() {  
        // 显示对象内容  
    }  
};  
  
int main() {  
    QScopedPointer<MyClass> ptr(new MyClass); // 创建一个 MyClass 对象,QScopedPointer 管理其生命周期  
  
    // 使用 data() 方法访问对象  
    MyClass* rawPtr = ptr.data(); // 返回原始指针,QScopedPointer 仍然拥有这个对象  
    rawPtr->show(); // 显示对象内容  
  
    // 使用 take() 方法转移对象所有权  
    MyClass* takenPtr = ptr.take(); // take() 返回原始指针,QScopedPointer 不再拥有这个对象  
    takenPtr->show(); // 显示对象内容,然后释放 takenPtr,不调用 MyClass 的析构函数  
  
    return 0;  
}

如下示例:

#include <QScopedPointer>  
  
class MyClass {  
public:  
    MyClass() {  
        // 初始化操作  
    }  
    ~MyClass() {  
        // 清理操作  
    }  
    void show() {  
        // 显示对象内容  
    }  
};  
  
int main() {  
    QScopedPointer<MyClass> ptr(new MyClass); // 创建一个 MyClass 对象,QScopedPointer 管理其生命周期  
  
    // 使用 data() 方法访问对象  
    MyClass* rawPtr = ptr.data(); // 返回原始指针,QScopedPointer 仍然拥有这个对象  
    rawPtr->show(); // 显示对象内容  
  
    // 使用 take() 方法转移对象所有权  
    MyClass* takenPtr = ptr.take(); // take() 返回原始指针,QScopedPointer 不再拥有这个对象  
    takenPtr->show(); // 显示对象内容,然后释放 takenPtr,不调用 MyClass 的析构函数  
  
    return 0;  
}

到此这篇关于Qt 智能指针QScopedPoint用法小结的文章就介绍到这了,更多相关Qt 智能指针QScopedPoint内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++中explict关键字用法

    C++中explict关键字用法

    这篇文章主要介绍了C++中explict关键字用法的相关资料,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
    2016-05-05
  • C语言判断字符串是否回文三种方法实例

    C语言判断字符串是否回文三种方法实例

    回文就是字符串中心对称,从左向右读和从右向左读的内容是一样的,下面这篇文章主要给大家介绍了关于C语言判断字符串是否回文的三种方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-03-03
  • C语言定义字符串数组简单代码示例

    C语言定义字符串数组简单代码示例

    在C语言中字符串数组是用来存储多个字符串的,可以通过字符数组或指针数组的方式定义,这篇文章主要介绍了C语言定义字符串数组的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • C语言写一个散列表

    C语言写一个散列表

    这篇文章主要介绍了C语言写一个散列表,散列表,就是下标可以为字母的数组。更多内容和小编一起学习下面内容吧
    2022-01-01
  • C++定时器实现和时间轮介绍

    C++定时器实现和时间轮介绍

    这篇文章主要介绍了C++定时器实现和时间轮介绍,定时器可以由很多种数据结构实现,比如最小堆、红黑树、跳表、甚至数组都可以,其本质都是拿到最小时间的任务,然后取出该任务并执行,更多相关内容介绍,需要的小伙伴可以参考一下
    2022-09-09
  • C++ primer超详细讲解泛型算法

    C++ primer超详细讲解泛型算法

    泛型编程,故如其名,是一个泛化的编程方式。其实现原理为程序员编写一个函数/类的代码示例,让编译器去填补出不同的函数实现
    2022-07-07
  • C++ 指向类成员的指针

    C++ 指向类成员的指针

    指向类成员的指针总的来讲可以分为两大类四小类(指向数据成员还是成员函数,指向普通成员还是静态成员)
    2020-03-03
  • 利用C语言实现页面置换算法的详细过程

    利用C语言实现页面置换算法的详细过程

    一个好的页面置换算法,应具有较低的页面更换频率,从理论上讲,应该保留最近重复访问的页面,将以后都不再访问或者很长时间内不再访问的页面调出,下面这篇文章主要给大家介绍了关于利用C语言实现页面置换算法的相关资料,需要的朋友可以参考下
    2022-11-11
  • C语言编程计算信噪比SNR理解学习

    C语言编程计算信噪比SNR理解学习

    这篇文章主要介绍了C语言编程信噪比SNR计算的理解学习,信噪比,英文名称叫做SNR或S/N(SIGNAL-NOISE RATIO)。是指一个电子设备或者电子系统中信号与噪声的比例
    2021-10-10
  • C++中stack的pop()函数返回值解析

    C++中stack的pop()函数返回值解析

    这篇文章主要介绍了C++中stack的pop()函数返回值,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07

最新评论