QScopedPointer类

template <typename T, typename Cleanup = QScopedPointerDeleter<T>> class QScopedPointer

QScopedPointer类存储指向动态分配对象的指针,并在析构时删除它。 更多...

头文件 #include <QScopedPointer>
CMakefind_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(mytarget PRIVATE Qt6::Core)
qmakeQT += core
继承自

QScopedArrayPointer

注意:本类中所有函数都是重入的

公开函数

QScopedPointer(T *p = nullptr)
~QScopedPointer()
T *data() const
T *get() const
boolisNull() const
voidreset(T *other = nullptr)
booloperator bool() const
booloperator!() const
T &operator*() const
T *operator->() const
booloperator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
booloperator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
booloperator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)
booloperator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)
booloperator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)
booloperator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)

详细介绍

手动管理堆分配的对象很难且易出错,常见的后果是代码泄漏内存且难以维护。QScopedPointer是一个小巧的实用类,通过将基于堆的内存所有权赋值给堆分配,大大简化了这一过程,更广泛地称为资源获取即初始化(RAII)。

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

它被手动删除调用所拖累。使用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);
}

编译器为QScopedPointer生成的代码与手动编写时相同。使用delete的代码是QScopedPointer使用者的候选(如果不是,可能是其他类型的智能指针,如QSharedPointer)。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());

自定义清理处理程序

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

以下是一些自定义清理处理程序:

  • QScopedPointerDeleter - 默认,使用delete删除指针
  • QScopedPointerArrayDeleter - 使用delete []删除指针。对于使用new []分配的指针,请使用此处理程序。
  • QScopedPointerPodDeleter - 使用free()删除指针。对于使用malloc()分配的指针,请使用此处理程序。
  • QScopedPointerDeleteLater - 通过调用它的deleteLater()来删除指针。对于积极参与QEventLoopQObject指针,请使用此处理程序。

您可以将自己的类作为处理程序传递,前提是它们有一个公开的静态函数void cleanup(T *pointer)

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

前置声明指针

可以在QScopedPointer中使用已经进行前置声明的类,只要在QScopedPointer需要清理时随时都可以获得该前置声明类的析构函数。

具体来说,这意味着包含指向前置声明类的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 implicitly
                             // generate them.
};

否则,编译器会输出有关无法析构MyPrivateClass的警告。

另请参阅QSharedPointer

成员函数文档

[显式 noexcept] QScopedPointer::QScopedPointer(T *p = nullptr)

构建此QScopedPointer实例并将指针设置为p

QScopedPointer::~QScopedPointer()

销毁此QScopedPointer对象。删除它所指向的对象。

[noexcept] T *QScopedPointer::data() const

返回此对象引用的指针的值。此QScopedPointer仍拥有指向的对象。

[noexcept] T *QScopedPointer::get() const

data相同。

[noexcept(...)] bool QScopedPointer::isNull() const

如果此对象引用nullptr,返回true

[noexcept] void QScopedPointer::reset(T *other = nullptr)

删除它正在指向的现有对象(如果有的话),并将指针设置为other。现在QScopedPointer拥有other并在其析构函数中删除它。

注意:当 "noexcept(Cleanup::cleanup(std::declval<T *>()))" 为真时,此函数不会抛出任何异常。

[显式] bool QScopedPointer::operator bool() const

如果包含的指针不是 nullptr,则返回 true。此函数适用于使用在 if-constructs 中,如下所示:

if (scopedPointer) {
    ...
}

另请参阅isNull()。

[noexcept] bool QScopedPointer::operator!() const

如果此对象引用nullptr,返回true

另请参阅isNull()。

T &QScopedPointer::operator*() const

提供对作用域指针对象的访问。

如果包含的指针是 nullptr,行为将是未定义的。

另请参阅isNull()。

[noexcept] T *QScopedPointer::operator->() const

提供对作用域指针对象的访问。

如果包含的指针是 nullptr,行为将是未定义的。

另请参阅isNull()。

相关非成员

[noexcept] bool operator!=(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)

如果 lhsrhs 指向不同的指针,则返回 true

[noexcept] bool operator!=(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)

如果 lhs 指向一个有效(即非空)的指针,则返回 true

另请参阅QScopedPointer::isNull

[noexcept] bool operator!=(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)

如果 rhs 指向一个有效(即非空)的指针,则返回 true

另请参阅QScopedPointer::isNull

[noexcept] bool operator==(const QScopedPointer<T, Cleanup> &lhs, const QScopedPointer<T, Cleanup> &rhs)

如果 lhsrhs 指向相同的指针,则返回 true

[noexcept] bool operator==(const QScopedPointer<T, Cleanup> &lhs, std::nullptr_t)

如果 lhs 指向 nullptr,则返回 true

另请参阅QScopedPointer::isNull

[noexcept] bool operator==(std::nullptr_t, const QScopedPointer<T, Cleanup> &rhs)

如果 rhs 指向 nullptr,则返回 true

另请参阅QScopedPointer::isNull

© 2024 Qt公司有限公司。本文档贡献的文档版权属其各自所有者。本提供的文档遵守由自由软件基金会发布的 GNU自由文档许可(FDL)版本1.3 的条款。Qt及其相应的标志是芬兰和/或其他国家的Qt公司注册商标。所有其他商标均为其各自所有者的财产。