Skip to content
正常

QSharedData 用户自定义共享类路线

本索引收录 Qt 6.9.1 源码中 QSharedData 体系相关的已验证证据。这条路线用于用户自定义类的隐式/显式共享,与内置容器的 QArrayData 路线独立。

QSharedData(数据基类)

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

论点行号原文摘要解读
ref 成员是 mutable QAtomicInt:22mutable QAtomicInt ref;mutable 是必要的:const 拷贝也需要修改 ref。
构造函数 ref 初始化为 0:24QSharedData() noexcept : ref(0) { }创建时无指针持有,ref=0。被 QSharedDataPointer 接管后才变 1。与 QArrayData 的 ref_=1 不同。
拷贝构造也 ref=0:25QSharedData(const QSharedData &) noexcept : ref(0) { }clone 出的新对象 ref 从 0 开始。
赋值运算符 = delete:26QSharedData &operator=(const QSharedData &) = delete;防止意外覆盖引用计数。

QSharedDataPointer(隐式共享智能指针)

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

论点行号原文摘要解读
detach 条件:d!=null && ref!=1:41if (d && d->ref.loadRelaxed() != 1) detach_helper();注意是 !=1 不是 >1,ref==0 也触发(QAdoptSharedDataTag 场景)。
拷贝构造:浅拷贝 + ref():66-67d(o.d) { if (d) d->ref.ref(); }O(1),与 QArrayDataPointer 对称。
析构:deref false 时 delete:57if (d && !d->ref.deref()) delete d.get();ref 从 1 减到 0 时释放。
detach_helper:clone → ref → deref 旧 → reset:243-250T *x = clone(); x->ref.ref(); if (!d.get()->ref.deref()) delete d.get(); d.reset(x);clone()=new T(*d),新对象 ref=0→ref()→1,旧 deref 可能释放。
reset() 有自赋值保护:69-78if (ptr != d.get()) { ... }ptr==d.get() 时跳过。
operator= 通过 reset() 实现:80-84reset(o.d.get());自赋值时 reset 内部跳过。

QExplicitlySharedDataPointer(显式共享)

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

论点行号原文摘要解读
非 const operator->() 不调用 detach():138-139T *operator->() noexcept { return d.get(); }「显式共享」的核心含义:拿到指针后不会自动深拷贝。
非 const operator*() 也不调用 detach():131T &operator*() const { return *(d.get()); }甚至标记为 const——不修改指针状态。

QAdoptSharedDataTag(零开销所有权转移)

论点行号原文摘要解读
构造时不 ref,配合 take() 实现零原子操作转移:63-64QSharedDataPointer(T *data, QAdoptSharedDataTag) noexcept : d(data) {}同线程内转移所有权,避免不必要的原子操作。

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