欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > 【Qt】: QPointer详解

【Qt】: QPointer详解

2025/2/22 2:03:38 来源:https://blog.csdn.net/weixin_39568531/article/details/145326202  浏览:    关键词:【Qt】: QPointer详解

考古: 《Qt智能指针之QScopedPointer》

QPointer是Qt框架中的一个智能指针类,用于安全地管理QObject派生对象的指针。它的主要功能是自动将指针置为nullptr,当它所指向的QObject对象被销毁时。这在Qt应用程序中非常有用,因为QObject对象通常会在其父对象被销毁时自动销毁。

一、QPointer的特性和用法

  1. 自动置空

    • QPointer会在其指向的QObject对象被销毁时自动将自身置为nullptr。这可以防止悬空指针(dangling pointer)问题。
  2. 使用场景

    • 适用于需要在多个地方引用同一个QObject对象的场景,尤其是当对象的生命周期不由你直接控制时。
    • 常用于Qt信号和槽机制中,确保槽函数中使用的对象在信号发出时仍然有效。
  3. QSharedPointerQScopedPointer的区别

    • QPointer不负责对象的内存管理,它只是一个观察者。
    • QSharedPointerQScopedPointer负责对象的生命周期管理,前者通过引用计数,后者通过作用域。

二、示例代码

以下是一个简单的示例,展示如何使用QPointer

#include <QCoreApplication>
#include <QObject>
#include <QPointer>
#include <QDebug>class MyObject : public QObject {Q_OBJECT
public:MyObject() { qDebug() << "MyObject created"; }~MyObject() { qDebug() << "MyObject destroyed"; }
};int main(int argc, char *argv[]) {QCoreApplication a(argc, argv);MyObject* obj = new MyObject();QPointer<MyObject> ptr(obj);qDebug() << "Pointer is valid:" << !ptr.isNull();delete obj;  // Manually delete the objectqDebug() << "Pointer is valid after deletion:" << !ptr.isNull();return a.exec();
}
    1. 创建对象
      MyObject* obj = new MyObject();:动态分配一个MyObject实例。
    1. 使用QPointer
      -QPointer<MyObject> ptr(obj);:创建一个QPointer,指向obj
    1. 检查指针有效性
      ptr.isNull():检查QPointer是否为空。
    1. 删除对象
      delete obj;:手动删除obj,此时ptr会自动变为nullptr
    1. 输出结果
      在对象被删除后,ptr.isNull()返回true,表明指针已被置空。

关键点

  • 安全性QPointer提供了一种安全的方式来引用QObject对象,避免悬空指针。
  • 非所有权QPointer不负责对象的内存管理,只是一个观察者。
  • 适用性:适用于需要在多个地方引用同一个QObject对象的场景,尤其是在信号和槽机制中。

三、QPointer 源码赏析

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/#ifndef QPOINTER_H
#define QPOINTER_H#include <QtCore/qsharedpointer.h>
#include <QtCore/qtypeinfo.h>#ifndef QT_NO_QOBJECTQT_BEGIN_NAMESPACEclass QVariant;template <class T>
class QPointer
{Q_STATIC_ASSERT_X(!std::is_pointer<T>::value, "QPointer's template type must not be a pointer type");template<typename U>struct TypeSelector{typedef QObject Type;};template<typename U>struct TypeSelector<const U>{typedef const QObject Type;};typedef typename TypeSelector<T>::Type QObjectType;QWeakPointer<QObjectType> wp;
public:inline QPointer() { }inline QPointer(T *p) : wp(p, true) { }// compiler-generated copy/move ctor/assignment operators are fine!// compiler-generated dtor is fine!#ifdef Q_QDOC// Stop qdoc from complaining about missing function~QPointer();
#endifinline void swap(QPointer &other) { wp.swap(other.wp); }inline QPointer<T> &operator=(T* p){ wp.assign(static_cast<QObjectType*>(p)); return *this; }inline T* data() const{ return static_cast<T*>( wp.data()); }inline T* operator->() const{ return data(); }inline T& operator*() const{ return *data(); }inline operator T*() const{ return data(); }inline bool isNull() const{ return wp.isNull(); }inline void clear(){ wp.clear(); }
};
template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_MOVABLE_TYPE);template <class T>
inline bool operator==(const T *o, const QPointer<T> &p)
{ return o == p.operator->(); }template<class T>
inline bool operator==(const QPointer<T> &p, const T *o)
{ return p.operator->() == o; }template <class T>
inline bool operator==(T *o, const QPointer<T> &p)
{ return o == p.operator->(); }template<class T>
inline bool operator==(const QPointer<T> &p, T *o)
{ return p.operator->() == o; }template<class T>
inline bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
{ return p1.operator->() == p2.operator->(); }template <class T>
inline bool operator!=(const T *o, const QPointer<T> &p)
{ return o != p.operator->(); }template<class T>
inline bool operator!= (const QPointer<T> &p, const T *o)
{ return p.operator->() != o; }template <class T>
inline bool operator!=(T *o, const QPointer<T> &p)
{ return o != p.operator->(); }template<class T>
inline bool operator!= (const QPointer<T> &p, T *o)
{ return p.operator->() != o; }template<class T>
inline bool operator!= (const QPointer<T> &p1, const QPointer<T> &p2)
{ return p1.operator->() != p2.operator->() ; }template<typename T>
QPointer<T>
qPointerFromVariant(const QVariant &variant)
{return QPointer<T>(qobject_cast<T*>(QtSharedPointer::weakPointerFromVariant_internal(variant).data()));
}QT_END_NAMESPACE#endif // QT_NO_QOBJECT#endif // QPOINTER_H

QPointer 只有一个成员变量 QWeakPointer<QObjectType> wp; 几乎所有成员函数的操作都是对wp成员变量的操作。其他,比较简单,不过多赘述。

四、QWeakPointer

/****************************************************************************template <class T>
class QWeakPointer
{typedef T *QWeakPointer:: *RestrictedBool;typedef QtSharedPointer::ExternalRefCountData Data;public:typedef T element_type;typedef T value_type;typedef value_type *pointer;typedef const value_type *const_pointer;typedef value_type &reference;typedef const value_type &const_reference;typedef qptrdiff difference_type;bool isNull() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 || value == nullptr; }operator RestrictedBool() const Q_DECL_NOTHROW { return isNull() ? nullptr : &QWeakPointer::value; }bool operator !() const Q_DECL_NOTHROW { return isNull(); }T *data() const Q_DECL_NOTHROW { return d == nullptr || d->strongref.load() == 0 ? nullptr : value; }inline QWeakPointer() Q_DECL_NOTHROW : d(nullptr), value(nullptr) { }inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }#ifndef QT_NO_QOBJECT// special constructor that is enabled only if X derives from QObject
#if QT_DEPRECATED_SINCE(5, 0)template <class X>QT_DEPRECATED inline QWeakPointer(X *ptr) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr){ }
#endif
#endif#if QT_DEPRECATED_SINCE(5, 0)template <class X>QT_DEPRECATED inline QWeakPointer &operator=(X *ptr){ return *this = QWeakPointer(ptr); }
#endifQWeakPointer(const QWeakPointer &other) Q_DECL_NOTHROW : d(other.d), value(other.value){ if (d) d->weakref.ref(); }
#ifdef Q_COMPILER_RVALUE_REFSQWeakPointer(QWeakPointer &&other) Q_DECL_NOTHROW: d(other.d), value(other.value){other.d = nullptr;other.value = nullptr;}QWeakPointer &operator=(QWeakPointer &&other) Q_DECL_NOTHROW{ QWeakPointer moved(std::move(other)); swap(moved); return *this; }
#endifQWeakPointer &operator=(const QWeakPointer &other) Q_DECL_NOTHROW{QWeakPointer copy(other);swap(copy);return *this;}void swap(QWeakPointer &other) Q_DECL_NOTHROW{qSwap(this->d, other.d);qSwap(this->value, other.value);}inline QWeakPointer(const QSharedPointer<T> &o) : d(o.d), value(o.data()){ if (d) d->weakref.ref();}inline QWeakPointer &operator=(const QSharedPointer<T> &o){internalSet(o.d, o.value);return *this;}template <class X>inline QWeakPointer(const QWeakPointer<X> &o) : d(nullptr), value(nullptr){ *this = o; }template <class X>inline QWeakPointer &operator=(const QWeakPointer<X> &o){// conversion between X and T could require access to the virtual table// so force the operation to go through QSharedPointer*this = o.toStrongRef();return *this;}template <class X>bool operator==(const QWeakPointer<X> &o) const Q_DECL_NOTHROW{ return d == o.d && value == static_cast<const T *>(o.value); }template <class X>bool operator!=(const QWeakPointer<X> &o) const Q_DECL_NOTHROW{ return !(*this == o); }template <class X>inline QWeakPointer(const QSharedPointer<X> &o) : d(nullptr), value(nullptr){ *this = o; }template <class X>inline QWeakPointer &operator=(const QSharedPointer<X> &o){QSHAREDPOINTER_VERIFY_AUTO_CAST(T, X); // if you get an error in this line, the cast is invalidinternalSet(o.d, o.data());return *this;}template <class X>bool operator==(const QSharedPointer<X> &o) const Q_DECL_NOTHROW{ return d == o.d; }template <class X>bool operator!=(const QSharedPointer<X> &o) const Q_DECL_NOTHROW{ return !(*this == o); }inline void clear() { *this = QWeakPointer(); }inline QSharedPointer<T> toStrongRef() const { return QSharedPointer<T>(*this); }// std::weak_ptr compatibility:inline QSharedPointer<T> lock() const { return toStrongRef(); }#if defined(QWEAKPOINTER_ENABLE_ARROW)inline T *operator->() const { return data(); }
#endifprivate:#if defined(Q_NO_TEMPLATE_FRIENDS)
public:
#elsetemplate <class X> friend class QSharedPointer;template <class X> friend class QPointer;
#endiftemplate <class X>inline QWeakPointer &assign(X *ptr){ return *this = QWeakPointer<X>(ptr, true); }#ifndef QT_NO_QOBJECTtemplate <class X>inline QWeakPointer(X *ptr, bool) : d(ptr ? Data::getAndRef(ptr) : nullptr), value(ptr){ }
#endifinline void internalSet(Data *o, T *actual){if (d == o) return;if (o)o->weakref.ref();if (d && !d->weakref.deref())delete d;d = o;value = actual;}Data *d;T *value;
};

QWeakPointer有两个成员变量,
Data *d; T *value;
它自身在构造函数中只是接收指针变量,并赋值給成员函数,因此他也是也是观察者。其他比较简单,不过多赘述。关于Qt中的引用计数原理和实现,后续另外进行介绍。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词