Skip to content
正常

QVariant 类型擦除与 QMetaType 源码索引

本索引收录 Qt 6.9.1 源码中 QVariant + QMetaType 的已验证证据。

类型擦除(packedType 位域)

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

论点行号原文摘要解读
packedType 位域右移 2 位存 iface 指针qvariant.h:118, qvariant_p.h:77-79quintptr packedType : sizeof(QMetaType)*8 - 2 / 构造 packedType(quintptr(iface) >> 2) / Q_ASSERT((quintptr(iface) & 0x3) == 0)依赖 iface 4 字节对齐(低 2 位为 0),右移 2 位省 2 bit;typeInterface() 左移 2 位还原。无模板参数,靠运行时 iface 知类型。

SSO-like 存储

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

论点行号原文摘要解读
Data 联合体 + 内联阈值 3sizeof(void)qvariant.h:99-125MaxInternalSize = 3*sizeof(void*) / union { uchar data[MaxInternalSize]; PrivateShared *shared; double _forAlignment; }64 位=24 字节。double 成员强制 32 位系统也 8 字节对齐。
canUseInternalSpace 三条件qvariant.h:103-108RelocatableType && size<=MaxInternalSize && alignof(T)<=alignof(double)=8三条满足 placement-new 到 data.data,否则 customConstructShared 堆分配 + is_shared。

QMetaTypeInterface 虚表 + QMetaType 句柄

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

论点行号原文摘要解读
QMetaTypeInterface 是类型虚表:270-312size/alignment/flags/typeId + defaultCtr/copyCtr/moveCtr/dtor/equals/lessThan/debugStream/dataStream 函数指针注意无 canConvert/convert 字段(转换走全局注册表)。
QMetaType 是 iface 轻量句柄:338-480QMetaType(const QMetaTypeInterface *d) : d_ptr(d) {} / registerType/id 延迟注册只持 d_ptr 指针拷贝廉价。首次 id() 才进全局表。

setValue/value 双路 + 函数指针短路

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

论点行号原文摘要解读
setValue fast path / value fast pathqvariant.h:491-503, :752-767setValue: isDetached && type 匹配 → in-place assign,否则 fromValue / value: type 匹配 → static_cast,否则 convertfast path 零开销,slow path 走 construct/convert。
construct 函数指针短路qmetatype_p.h:166-206defaultCtr 为 null → memset / copyCtr 为 null → memcpytrivially copyable 类型绕过函数指针,Qt 内置类型快的根源。

convert 三层 fallback

源码文件:qtbase/src/corelib/kernel/qmetatype.cpp

论点行号原文摘要解读
canConvert/convert 三层:2390-2451, :2611-2672moduleHelper(内置转换表)→ customTypesConversionRegistry(用户注册)→ 特殊路径(枚举/容器/MetaObject)canConvert 用 nullptr 探测不实际转换。

Qt6 完全基于 QMetaType + 两处 breaking

源码文件:qtbase/src/corelib/kernel/qvariant.h / qvariant.cpp / qmetatype.h

论点行号原文摘要解读
QVariant::Type 全 deprecatedqvariant.h:141-216, :687QT_DEPRECATED_VERSION_X_6_0("Use QMetaType::Type instead.") enum Type / QVariant(QMetaType::Type) = deleteQt6 臣服 QMetaType。枚举值别名到 QMetaType::Xxx。
【Qt6 breaking】isNull 不再调类型 isNull()qvariant.cpp:2529-2547if (d.is_null || !metaType().isValid()) return true; if (flags & IsPointer) return get<void*>()==nullptr; return false; + 注释 This behavior has been changed from Qt 5Qt5 时空 QString/QDate 等 isNull() 返 true;Qt6 不再代理,breaking。
【Qt6 breaking】equals 类型不同不再通用 convertqvariant.cpp:2405-2426类型不同 → 仅 canBeNumericallyCompared→numericCompareqvCanConvertMetaObject→pointerCompare,否则 falseQt5 会 convert 后比;Qt6 只数值/指针特殊比较,breaking。
fromValue 强制 registerTypeqvariant.h:552, qvariant.cpp:2753mt.registerType(); 注释 we want the type stored in QVariant to always be registered保证 typeId() 可用。

拷贝三路(PrivateShared COW)

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

论点行号原文摘要解读
clonePrivate 三路qvariant.cpp:302-322is_shared → ref.ref()(COW)/ 小 trivially 隐式 memcpy / 小非 trivially copyConstruct大类型用 QVariant::PrivateShared(alignas(8) QAtomicInt ref,非 QSharedData);小类型不走 COW 每次 copy construct。

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