Skip to content
正常

QString 内存模型与编译期视图

本索引收录 Qt 6.9.1 源码中 QString 内存模型相关的已验证证据。COW 智能指针的通用机制(三成员、detach、needsDetach 短路、fromRawData 工厂)见 QArrayDataPointer COW 智能指针;数据头部字段与分配/增长链路见 QArrayData 容器共享数据头部;原子引用计数见 原子引用计数操作。本文件只收 QString 自己的内存模型声明与字面量视图机制。

类成员布局——QString 没有 SSO

源码文件:qtbase/src/corelib/text/qstring.h

论点行号原文摘要解读
QString 类私有成员只有一个 DataPointer d + 静态 _empty,无内联 buffer:1099-1100DataPointer d; static const char16_t _empty;全篇立论根基:QString 不走 std::string 式 SSO,所有字符数据要么在堆、要么指向字面量/静态 _empty,从不内联在对象里。
QString 内部数据头 typedef Data = QTypedArrayData<char16_t>:143typedef QTypedArrayData<char16_t> Data;头部指针的类型名。static_assert 保证 sizeof 不变。

源码文件:qtbase/src/corelib/text/qstringliteral.h

论点行号原文摘要解读
DataPointer 真身是 QStringPrivate = QArrayDataPointer<char16_t>:24using QStringPrivate = QArrayDataPointer<char16_t>;typedef 链定义在此(不在 qstring.h),因 QArrayDataPointer 模板在更底层的 qarraydatapointer.h,头依赖顺序要求。QArrayDataPointer<char16_t> 三字段(d/ptr/size)见 qarraydatapointer.md。

静态空对象 _empty(Qt6 替代 Qt5 sharedNull)

源码文件:qtbase/src/corelib/text/qstring.cpp

论点行号原文摘要解读
_empty 是单个 static char16_t(值=0),不是带头部的 sharedNull:76const char16_t QString::_empty = 0;Qt 5 有 QArrayData::sharedNull()(ref==-1 的静态头部),Qt 6.9.1 删了,改用最朴素的 char16_t 静态变量。空 QString 的 d 是 nullptr,ptr 借指 _empty

源码文件:qtbase/src/corelib/text/qstring.h

论点行号原文摘要解读
默认构造 constexpr 空体,零堆分配:1410constexpr QString::QString() noexcept {}依赖 DataPointer 默认构造把 d/ptr/size 全置 nullptr/0。连 _empty 都没指,首次 data()/unicode() 才回退 &_empty。这是「空视图」不是 SSO。

构造路径

源码文件:qtbase/src/corelib/text/qstring.cpp

论点行号原文摘要解读
QString(const QChar*, size) 三路径构造:2491-2504if (!unicode) d.clear(); else if (!size) d = fromRawData(&_empty, 0); else { d = DataPointer(size, size); memcpy(...); d.data()[size] = '\0'; }标准构造:空→空视图;非空→单次堆分配+memcpy+手写 null 终止符。注意 \0 由调用方写,不在 allocate 内自动加(PSV:指针可直传 C API)。

源码文件:qtbase/src/corelib/text/qstring.h

论点行号原文摘要解读
拷贝构造浅拷贝 d(other.d),O(1):1340-1341QString(const QString &other) noexcept : d(other.d) { }ref 管理下沉到 QArrayDataPointer 拷贝构造(那里调 ref())。

容量管理 resize/reserve/squeeze

源码文件:qtbase/src/corelib/text/qstring.cpp

论点行号原文摘要解读
resize 调 reallocData(Grow) + 写 null 终止符:2664-2672if (d->needsDetach() || needsReallocate(*this, size)) reallocData(size, Grow); d.size = size; if (d->allocatedCapacity()) d.data()[size] = u'\0';Grow 模式预留增长空间。空串视图 alloc=0 时不写终止符(_empty 本身是 0)。

源码文件:qtbase/src/corelib/text/qstring.h

论点行号原文摘要解读
reserve 用 KeepSize 扩张 + 置 CapacityReserved:1413-1419if (d.needsDetach() || asize >= capacity() - d.freeSpaceAtBegin()) reallocData(qMax(asize, size()), KeepSize); if (d.constAllocatedCapacity()) d.setFlag(Data::CapacityReserved);KeepSize 不预留额外增长系数。CapacityReserved 标志让后续 detach 时保留预约容量不被截短。
squeeze 收容量到 size + 清 CapacityReserved:1421-1429if (!d.isMutable()) return; if (d.needsDetach() || size() < capacity()) reallocData(d.size, KeepSize); if (d.constAllocatedCapacity()) d.clearFlag(Data::CapacityReserved);reserve 的反操作。不可变对象(fromRawData 视图,isMutable()==false)直接 return。

容量增长策略(qNextPowerOfTwo 取 2 的幂)、单次连续 malloc、FooterSize 补偿、in-place reallocate 免拷贝,见 QArrayData · 分配链路与增长策略

编译期视图——QStringLiteral / _s / fromRawData

源码文件:qtbase/src/corelib/text/qstringliteral.h

论点行号原文摘要解读
QStringLiteral 不构造头部,是 {nullptr, literal, N-1} 编译期 fromRawData:24-38qMakeStringPrivate return { nullptr, str, N - 1 }; 宏展开 QString(qMakeStringPrivate(QT_UNICODE_LITERAL(str)))Qt 5 用 Q_STATIC_ARRAY_DATA 在编译期构造 QArrayData 头部(ref=-1);Qt 6.9.1 完全不构造头部,d=nullptr 无引用计数,ptr 直指 .rodata 字面量,零运行期分配。

源码文件:qtbase/src/corelib/text/qstring.h

论点行号原文摘要解读
operator 字面量后缀 _s 与 QStringLiteral 同构:1731-1734return QString(QStringPrivate(nullptr, const_cast<char16_t *>(str), qsizetype(size)));两条字面量转 QString 路径(宏、UDL)走同一套 nullptr-head 模式。

源码文件:qtbase/src/corelib/text/qstring.cpp

论点行号原文摘要解读
QString::fromRawData 包外部指针为视图:9381-9384return QString(DataPointer::fromRawData(const_cast<char16_t *>(...unicode), size));不持有不拷贝。DataPointer::fromRawData 工厂(见 qarraydatapointer.md)返回 {nullptr, rawData, length}。

fromRawData 视图触发 detach 的完整闭环(d==nullptr 时 needsDetach 的 !d 短路)见 QArrayDataPointer · ref/deref 与 needsDetach

QStringView 不持有

源码文件:qtbase/src/corelib/text/qstringview.h

论点行号原文摘要解读
QStringView 只存 m_data + m_size 两字段:432-439const storage_type *m_data = nullptr; qsizetype m_size = 0;(Qt6 走 #else 分支 m_size 在前)纯只读视图,两 machine word,无 DataPointer/d 头部/引用计数。生命周期由调用方保证(类似 std::string_view)。

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