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的警告。