栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

QPointer、QScopedPointer、QSharedDataPointer等指针用法总结

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

QPointer、QScopedPointer、QSharedDataPointer等指针用法总结

1 . QPointer

这是一个模板类,是一个警卫、看守指针。QPointer的行为非常类似C++的普通指针T*。和C++的普通指针T*有一点不同的是:当指针指向的对象被销毁时,该指针自动会被清除,即置为nullptr,而C++的普通指针指向的对象被销毁,如果不人工置为nullptr,则不会被自动清除,一般会成为悬垂指针,即野指针。QPointer中的T类型必须是QObject的子类。

当你需要保存一个指向QObject的子类对象(为了便于后文描述,称该对象为A)但该对象被其它对象(为了便于后文描述,称该对象为B)占用时,警卫、看守指针在这种情况下就非常有用。当B删除销毁了A时,使用QPointer可以测试其指向的对象是否有效。如下代码:

  QPointer label = new QLabel;
      label->setText("&Status:");
      ...
      if (label)
          label->show();

当代码执行到第3行时,第1行new出来的QLabel对象在其它地方被delete了,则label就会自动被置为nullptr,从而导致第4、5行代码不会被执行。如果是C++普通指针,则不会被置为nullptr,代码执行到第4行时会崩溃。

一些在C++普通指针上执行的函数和操作符对 QPointer同样适用,没啥区别。但指针算术操作符是个例外,对 QPointer来说,指针算术操作符+、-、++、--仅仅用在 QObject子类类型的数组上。

你可以从一个T*类型的指针或另外一个同类型的QPointer构造或赋值出一个新的警卫、看守指针QPointer

你可以通过operator==() 、 operator!=()比较两个警卫、看守指针QPointer是否指向相同的对象或不同的对象;你也可以通过*x 或x->解引用指向的对象。你可以通过isNull()判断指向的对象是否为空。

警卫、看守指针QPointer能自动转换到T*的C++普通指针,所以你可以放心地混合使用T*类型的C++普通指针和QPointer。这意味着下面的代码是可行的:

 QPointer label = new QLabel;

   ............


void fun(QLabel* p)
{
    ............
}

.......

fun(label);

而不必要特意将fun函数的参数定义为QPointer,即下述代码是没多大价值的:

 QPointer label = new QLabel;

   ............


void fun(QPointer p)
{
    ............
}

.......

fun(label);

当你需要长时间保存某个QObject子类的对象时,用QPointer指针。

注意:QPointer封装的指针的类型必须是QObject子类,否则编译器、连接器会报错。

2.QWeakPointer、QSharedPointer

    这两个指针和STL的std::shared_ptr 、std::weak_ptr作用相同,参见《C++ STL 四种智能指针》文章描述。

3 QScopedPointer

  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;
  }

上面的函数有很多退出点,为了删除new出的对象,每个退出点都加入了delete,这使得程序臃肿不堪,可读性、可维护性大大降低。用QScopedPointer改写上述代码后,简化了很多,如下:

void myFunction(bool useSubClass)
  {
      // assuming that MyClass has a virtual destructor
      QScopedPointer p(useSubClass ? new MyClass() : new MySubClass);
      QScopedPointer device(handsOverOwnership());

      if (m_value > 3)
          return;

      process(device);
  }

待用const限定符的对象也可以被QScopedPointer表示,如下:

      const QWidget *const p = new QWidget();
      // is equivalent to:
      const QScopedPointer p(new QWidget());

      QWidget *const p = new QWidget();
      // is equivalent to:
      const QScopedPointer p(new QWidget());

      const QWidget *p = new QWidget();
      // is equivalent to:
      QScopedPointer p(new QWidget());
 

用malloc分配的数组对象不能用delete删除,QScopedPointer模板的第二个参数被用来定义一个删除器。下列这些自定义的删除已经存在了:

  • QScopedPointerDeleter 。默认删除器。用delete删除指针。
  • QScopedPointerArrayDeleter。调用delete[]删除new[]出来的数组指针。
  • QScopedPointerPodDeleter。调用free删除malloc出来的指针。
  • QScopedPointerDeleteLater 。通过调用Qt的deleteLater()函数来删除对象。

你可以提供自定义删除器,自定义删除器必须满足:

  • 自定义删除器类必须提供一个静态公有的如下方法。
void cleanup(T *pointer)

如下为自定义的删除器:

  // this struct calls "myCustomDeallocator" to delete the pointer
  struct ScopedPointerCustomDeleter
  {
      static inline void cleanup(MyCustomClass *pointer)
      {
          myCustomDeallocator(pointer);
      }
  };

  // QScopedPointer using a custom deleter:
  QScopedPointer customPointer(new MyCustomClass);

4.QSharedDataPointer、QExplicitlySharedDataPointer

这两个参见Qt Assistant ,里面讲的很详细,这里不再讲解。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/862685.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号