Skip to content
正常

Qt 智能指针家族源码索引

本索引收录 Qt 6.9.1 源码中 Qt 智能指针家族相关的已验证证据。QSharedData 那条「ref 长在数据类里」的内部引用计数路线另见 QSharedData 用户自定义共享类路线(含 QSharedDataPointer/QExplicitlySharedDataPointer 的 detach 差异);原子操作底层见 原子引用计数操作。本文件只收 QSharedPointer / QWeakPointer / QScopedPointer / QPointer 这条「ref 在外部 refcount 块」的路线。

ExternalRefCountData——双计数地基

源码文件:qtbase/src/corelib/tools/qsharedpointer_impl.h

论点行号原文摘要解读
ExternalRefCountData 同时持有 weakref/strongref 两计数 + destroyer 函数指针:108-113struct ExternalRefCountData { ... QBasicAtomicInt weakref; QBasicAtomicInt strongref; DestroyerFn destroyer; };refcount 块本身是「ref-counted ref-counter」:strongref 管对象寿命、weakref 管 refcount 块自身寿命。是整个家族的地基。
构造时 strongref=1、weakref=1:115-120strongref.storeRelaxed(1); weakref.storeRelaxed(1);weakref 多一个兜底——只要还有强引用,块至少被一个 weakref 持有,不会被提前 delete。
强引用 deref 分阶段:strongref 归零 destroy 对象,weakref 归零 delete 块:511-519if (!dd->strongref.deref()) dd->destroy(); if (!dd->weakref.deref()) delete dd;两阶段析构:对象先死、refcount 块后死(weakref 可能仍被 QWeakPointer 持有)。destroy() 仅调 destroyer 函数指针,无复活机制。
~ExternalRefCountData 断言 weakref==0 且 strongref<=0:122Q_ASSERT(!weakref.loadRelaxed()); Q_ASSERT(strongref.loadRelaxed() <= 0);确认块删除的两个前置条件。
strongref/weakref 是 QBasicAtomicInt,不经 RefCount 层:111-112QBasicAtomicInt weakref; QBasicAtomicInt strongref;平台原生原子操作;QSharedPointer 计数不经 qrefcount.h 的 -1 静态包装(与 QSharedData::ref 的裸 QAtomicInt、QArrayData 经 RefCount 是三套不同实现)。

QWeakPointer——只动 weakref、不阻析构

源码文件:qtbase/src/corelib/tools/qsharedpointer_impl.h

论点行号原文摘要解读
析构/拷贝只 ref/deref weakref、不碰 strongref:618-622, :671-672~QWeakPointer() { if (d && !d->weakref.deref()) delete d; } / 拷贝 { if (d) d->weakref.ref(); }与 QSharedPointer 的 d->weakref.ref(); d->strongref.ref(); 对位——弱引用加减完全不动 strongref,故不阻对象析构。
weak→strong 升级:toStrongRef/lock 委托构造,CAS 实际在 internalSet:558-584, :707-709while (tmp > 0) { if (o->strongref.testAndSetRelaxed(tmp, tmp+1)) break; ... } if (tmp > 0) o->weakref.ref(); else o = nullptr;CAS 循环只在 strongref>0 时 +1 升级;对象已析构(strongref≤0)则失败、value 置 null。toStrongRef/lock 本体仅一行委托。

自定义 deleter——子类附加存储

源码文件:qtbase/src/corelib/tools/qsharedpointer_impl.h

论点行号原文摘要解读
ExternalRefCountWithCustomDeleter 子类把用户 deleter + 指针附加在 refcount 块后:147-208struct ExternalRefCountWithCustomDeleter: public ExternalRefCountData { CustomDeleter<T,Deleter> extra; ... static Self *create(...) { Self *d = ::operator new(sizeof(Self)); new (&d->extra) CustomDeleter(...); new (d) BaseClass(actualDeleter); } };基类只存 destroyer 函数指针(指静态 deleter),真正用户 deleter 走子类 extra 成员;sizeof 随 Deleter 类型动态,一次 ::operator new 分配。

QEnableSharedFromThis——sharedFromThis 回填

源码文件:qtbase/src/corelib/tools/qsharedpointer_impl.h

论点行号原文摘要解读
对象持 mutable QWeakPointer weakPointer,构造时回填:522-527, :811-831class QEnableSharedFromThis { ... QSharedPointer<T> sharedFromThis() { return QSharedPointer<T>(weakPointer); } ... mutable QWeakPointer<T> weakPointer; };QSharedPointer 构造经 enableSharedFromThis 回填该 weak 成员,使对象能安全拿到指向自己的 shared,避免裸 this 再造 QSharedPointer 导致双计数。

QPointer——Qt6 实现(委托 QWeakPointer + strongref=-1 哨兵)

源码文件:qtbase/src/corelib/kernel/qpointer.h

论点行号原文摘要解读
QPointer 是独立模板类(非 typedef),内部唯一数据成员是 QWeakPointer:17-37, :74-83template <class T> class QPointer { QWeakPointer<QObjectType> wp; public: QPointer(T *p) : wp(p, true) { } T* data() const { return wp.internalData(); } };Qt5 是 typedef QWeakPointer<QObject>,Qt6 改独立模板类但本质仍是 QWeakPointer 薄封装。wp(p, true) 走 QWeakPointer 私有构造(friend)。

源码文件:qtbase/src/corelib/tools/qsharedpointer.cpp

论点行号原文摘要解读
getAndRef 在 QObjectPrivate::sharedRefcount 挂块,strongref=-1 哨兵、weakref=2:1528-1556, :331-334x->strongref.storeRelaxed(-1); x->weakref.storeRelaxed(2); // the QWeakPointer + the QObject itselfstrongref=-1 表示「QObject 不被共享、仅跟踪寿命」。这正是 QPointer 不能 toStrongRef 的根源——internalSet 的 tmp>0 守卫不满足,checkQObjectShared 会 qWarning 拒绝。QObjectPrivate::sharedRefcount 是 QAtomicPointer(qobject_p.h:216)。

QScopedPointer——栈上独占 RAII

源码文件:qtbase/src/corelib/tools/qscopedpointer.h

论点行号原文摘要解读
模板<T, Cleanup>,析构调 Cleanup::cleanup,禁拷贝移动:69-82, :14-30class QScopedPointer { ... ~QScopedPointer() { Cleanup::cleanup(this->d); } Q_DISABLE_COPY_MOVE(QScopedPointer) };对位 std::unique_ptr。默认 Cleanup=QScopedPointerDeleter(delete)。
QScopedArrayPointer 数组特化,delete[] + operator[]:190-215, :32-49class QScopedArrayPointer : public QScopedPointer<T, Cleanup> { T& operator[](qsizetype i) { return this->d[i]; } };默认 Cleanup=QScopedPointerArrayDeleter(delete[])。对位 std::unique_ptr<T[]>。

Qt6 deprecated 态度

源码文件:qtbase/src/corelib/tools/qscopedpointer.h

论点行号原文摘要解读
仅 take()(6.1)/swap()(6.2)成员被 deprecated,类本身未整体 deprecated:128-143, :177-182, :217-221, :239-243QT_DEPRECATED_VERSION_X_6_1("Use std::unique_ptr instead, and call release().") T *take() / QT_DEPRECATED_VERSION_X_6_2(...) void swap(...)只有这两个成员函数触发警告,构造/析构/operator*/data/reset 都无警告。类未整体 deprecated。
QSharedPointer 全文无 deprecated 标记qsharedpointer.h 全文grep QT_DEPRECATED 零结果QSharedPointer 仍是官方一等公民,且提供 std::shared_ptr 兼容 API(lock/owner_before/owner_equal/owner_hash/qobject_pointer_cast)。

AwesomeQt v0.3.0-13-g31f4d47 · 31f4d47 · 2026-09-22 · CHECKED-BY: CI