QScopedPointer的了解

QT 智能指针 QPointer QScopedPointer QSharedPointer QWeakPointer QSharedDataPointer 隐式共享 显示共享-CSDN博客

本文摘录自上面的文章 

其类似于C++11中的unique_ptr,用于管理动态分配的对象独占所有权,即同一时间只能有一个QScopedPointer指向该对象

QScopedPointer使用了RAII(资源获取即初始化)技术,当QScopedPointer被销毁时,它将自动释放所管理的对象的内存

QScopedPointer不支持拷贝和赋值操作,这是为了避免在多个指针之间共享所有权的问题。

如果需要在多个指针之间转移所有权,应该使用QSharedPointer或QWeakPointer

它将通过分配的空间(new)赋值给基于的内存,通常称为RAII(resource acquisition is initialization)。

下面的内容来自Qt的帮助文档 

The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon destruction.

QScopedPointer类存储了一个指针(指向一个动态分配的对象),删除它当析构的时候。

Managing heap allocated objects manually is hard and error prone, with the common result that code leaks memory and is hard to maintain. QScopedPointer is a small utility class that heavily simplifies this by assigning stack-based memory ownership to heap allocations, more generally called resource acquisition is initialization(RAII).

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

QScopedPointer guarantees that the object pointed to will get deleted when the current scope disappears.

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

Consider this function which does heap allocations, and has various exit points:

考虑这个函数,它做堆分配,并有不同的退出点:
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;
  }

It's encumbered by the manual delete calls. With QScopedPointer, the code can be simplified to:

它受到手动删除调用的阻碍。使用QScopedPointer,代码可以简化为:

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

The code the compiler generates for QScopedPointer is the same as when writing it manually. Code that makes use of delete are candidates for QScopedPointer usage (and if not, possibly another type of smart pointer such as QSharedPointer). QScopedPointer intentionally has no copy constructor or assignment operator, such that ownership and lifetime is clearly communicated.

编译器为QScopedPointer生成的代码与手动编写时相同。使用delete的代码是QScopedPointer使用的候选对象(如果没有,可能是另一种智能指针,如QSharedPointer)。QScopedPointer故意没有复制构造函数或赋值操作符,这样所有权和生命周期就被清楚地传达了。

The const qualification on a regular C++ pointer can also be expressed with a QScopedPointer:

普通c++指针上的const限定符也可以用QScopedPointer来表示:


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

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

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

    QWidget w;
    QWidget * const p = &w;
    QWidget w1;
    p = &w1;

 提示:

error: assignment of read-only variable 'p'
     p = &w1;
       ^

p是只读变量,不可修改

    QWidget w;
    const QWidget * p = &w;
    p->adjustSize();

 

提示: 

error: passing 'const QWidget' as 'this' argument discards qualifiers [-fpermissive]
     p->adjustSize();
                   ^

const对象是不可以访问类的非const函数的。

 Custom Cleanup Handlers

自定义清理处理程序

Arrays as well as pointers that have been allocated with malloc must not be deleted using delete. QScopedPointer's second template parameter can be used for custom cleanup handlers.

分配了malloc的数组和指针不能使用delete删除。QScopedPointer的第二个模板参数可用于自定义清理处理程序。

The following custom cleanup handlers exist:

存在以下自定义清理处理程序:

  • QScopedPointerDeleter - the default, deletes the pointer using delete
  • QScopedPointerDeleter——默认值,使用delete删除指针
  • QScopedPointerArrayDeleter - deletes the pointer using delete []. Use this handler for pointers that were allocated with new [].
  • QScopedPointerArrayDeleter—使用delete[]删除指针。对于用new[]分配的指针使用此处理程序。
  • QScopedPointerPodDeleter - deletes the pointer using free(). Use this handler for pointers that were allocated with malloc().
  • QScopedPointerPodDeleter—使用free()删除指针。对于使用malloc()分配的指针使用此处理程序。
  • QScopedPointerDeleteLater - deletes a pointer by calling deleteLater() on it. Use this handler for pointers to QObject's that are actively participating in a QEventLoop.
  • QScopedPointerDeleteLater -通过对指针调用deleteLater()来删除指针。使用这个处理程序指向QObject的指针,这些指针正在积极参与QEventLoop。

  // this QScopedPointer deletes its data using the delete[] operator:
  QScopedPointer<int, QScopedPointerArrayDeleter<int> > arrayPointer(new int[42]);

  // this QScopedPointer frees its data using free():
  QScopedPointer<int, QScopedPointerPodDeleter> podPointer(reinterpret_cast<int *>(malloc(42)));

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

  // QScopedPointer using a custom deleter:
  QScopedPointer<MyCustomClass, ScopedPointerCustomDeleter> customPointer(new MyCustomClass);

 Forward Declared Pointers

前向声明指针

Classes that are forward declared can be used within QScopedPointer, as long as the destructor of the forward declared class is available whenever a QScopedPointer needs to clean up.

前向声明的类可以在QScopedPointer中使用,只要当QScopedPointer需要清理时,前向声明的类的析构函数可用。

Concretely, this means that all classes containing a QScopedPointer that points to a forward declared class must have non-inline constructors, destructors and assignment operators:

具体来说,这意味着所有包含指向前向声明类的QScopedPointer的类必须具有非内联构造函数、析构函数和赋值操作符:

 class MyPrivateClass; // forward declare MyPrivateClass

  class MyClass
  {
  private:
      QScopedPointer<MyPrivateClass> privatePtr; // QScopedPointer to forward declared class

  public:
      MyClass(); // OK
      inline ~MyClass() {} // VIOLATION - Destructor must not be inline

  private:
      Q_DISABLE_COPY(MyClass) // OK - copy constructor and assignment operators
                               // are now disabled, so the compiler won't implicitely
                               // generate them.
  };

Otherwise, the compiler outputs a warning about not being able to destruct MyPrivateClass. 

否则,编译器将输出一个关于无法销毁MyPrivateClass的警告。

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,所有 权转移到
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lpl还在学习的路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值