海外网站入口,网站项目建设计划,陕西网站备案注销,我想给企业做网站怎么做目录 QStringQTypedArrayDataQTypedArrayDataQLatin1StringQStringLiteral乱码 QStringRef QString
QString 存储16位QChar的字符串#xff0c;其中每个QChar对应一个 UTF-16代码单元。QString 使用#xff08;写入时复制copy-on-write#xff09;来减少内存使用并避免不必… 目录 QStringQTypedArrayDataQTypedArrayDataQLatin1StringQStringLiteral乱码 QStringRef QString
QString 存储16位QChar的字符串其中每个QChar对应一个 UTF-16代码单元。QString 使用写入时复制copy-on-write来减少内存使用并避免不必要的数据复制。这也有助于减少存储16位字符而不是8位字符的固有开销。
除了QString之外Qt还提供了存储原始字节和传统8位“\0”结尾字符串的QByteArray类。在大多数情况下使用QStringUnicode支持使得应用程序将很容易翻译。使用QByteArray类时合适的两种主要情况是需要存储原始二进制数据时以及内存保护至关重要时如在嵌入式系统中。
typedef QStringData Data;
typedef QTypedArrayDataushort QStringData;
class Q_CORE_EXPORT QString
{
public:typedef QStringData Data;//构造函数、拷贝函数、赋值运算符...........//字符串属性函数、字符串操作函数,修改、比较、查找..........
private:Data *d;
};QString内部除了定义的函数之外成员变量只有Data类型的指针指向字符数据地址。内部采用共享机制在QString对象赋值时只是类似智能指针执行浅拷贝简单复制指针d的值增加引用计数。同时QString采用写时复制机制只在修改数据时执行深拷贝复制字符数据并进行写操作。
QString在构造时调用QTypedArray的allocate函数将返回的地址赋值给指针d。以QChar为参数的构造函数size设置为1data返回地址开始存储字符数据末尾存储结束字符。
QString::QString(QChar ch)
{d Data::allocate(2);Q_CHECK_PTR(d);d-size 1;d-data()[0] ch.unicode();d-data()[1] \0;
}以QString的const 为参数的拷贝构造函数只是复制指针ref()增加计数值。
inline QString::QString(const QString other) noexcept : d(other.d)
{ Q_ASSERT(other ! this); d-ref.ref(); }析构函数中当引用计数为零时才会调用deallocate函数释放内存。
inline QString::~QString() { if (!d-ref.deref()) Data::deallocate(d); }在使用left()、mid()等字符串操作时会修改字符串此时会创建新的QString对象并在构造函数使用memcpy()进行深拷贝。
QString QString::left(int n) const
{if (uint(n) uint(d-size))return *this;return QString((const QChar*) d-data(), n);
}QTypedArrayData
QString的数据存放在指针d指向的对象中对象类型为QTypedArrayData继承自QArrayData。 QTypedArrayData重写的data()、allocate()、reallocateUnaligned()、deallocate()、sharedNull()都是直接调用了父结构体的函数此外还基于data()封装了一些迭代器操作。
在QString中类模板QTypedArrayData的模板实参T为ushort所以是以两字节的方式存储字符数据的。data函数的返回值为ushort类型的指针后续在QString中通过data()返回指针的[]运算符函数对字符数据进行操作。
template class T
struct QTypedArrayData: QArrayData
{typedef T* iterator;typedef const T* const_iterator;T *data() { return static_castT *(QArrayData::data()); }const T *data() const { return static_castconst T *(QArrayData::data()); }iterator begin(iterator iterator()) { return data(); }iterator end(iterator iterator()) { return data() size; }const_iterator begin(const_iterator const_iterator()) const { return data(); }const_iterator end(const_iterator const_iterator()) const { return data() size; }const_iterator constBegin(const_iterator const_iterator()) const { return data(); }const_iterator constEnd(const_iterator const_iterator()) const { return data() size; }class AlignmentDummy { QArrayData header; T data; };Q_REQUIRED_RESULT static QTypedArrayData *allocate(size_t capacity,AllocationOptions options Default){Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));return static_castQTypedArrayData *(QArrayData::allocate(sizeof(T),Q_ALIGNOF(AlignmentDummy), capacity, options));}static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity,AllocationOptions options Default){Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));return static_castQTypedArrayData *(QArrayData::reallocateUnaligned(data, sizeof(T),capacity, options));}static void deallocate(QArrayData *data){Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));QArrayData::deallocate(data, sizeof(T), Q_ALIGNOF(AlignmentDummy));}static QTypedArrayData *fromRawData(const T *data, size_t n,AllocationOptions options Default) { //.............}static QTypedArrayData *sharedNull() noexcept{Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));return static_castQTypedArrayData *(QArrayData::sharedNull());}static QTypedArrayData *sharedEmpty(){Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));return allocate(/* capacity */ 0);}#if !defined(QT_NO_UNSHARABLE_CONTAINERS)static QTypedArrayData *unsharableEmpty(){Q_STATIC_ASSERT(sizeof(QTypedArrayData) sizeof(QArrayData));return allocate(/* capacity */ 0, Unsharable);}
#endif
};QTypedArrayData
QTypedArrayData重写的data()、allocate()、reallocateUnaligned()、deallocate()、sharedNull()都是直接调用了父结构体QArrayData的函数所以字符数据和基础的操作都定义在QArrayData中QArrayData即数据容器。
[ref|size|alloc|reserve|offset|--the real data--]struct Q_CORE_EXPORT QArrayData
{QtPrivate::RefCount ref;int size;uint alloc : 31;uint capacityReserved : 1;qptrdiff offset; //从标头开头开始的字节数void *data(){Q_ASSERT(size 0 || offset 0 || size_t(offset) sizeof(QArrayData));return reinterpret_castchar *(this) offset;}const void *data() const {//.......}//这是指数组数据的可变性而不是 QArrayData 中数据成员表示的“标头数据”。//共享数据数组和标头仍必须遵循 COW 原则。bool isMutable() const { return alloc ! 0; }enum AllocationOption {//内存分配方式CapacityReserved 0x1,//调整内存大小或克隆时至少保留原始容量大小。
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)Unsharable 0x2,//非共享的在克隆时必须重新分配内存
#endifRawData 0x4,//如果设置了RawData分配内存时就会忽略填充而使数据紧贴在QArrayData头之后。Grow 0x8,//会分配超出用户要求的内存达到比用户要求数量更大的下一个2次幂Default 0//};Q_DECLARE_FLAGS(AllocationOptions, AllocationOption)size_t detachCapacity(size_t newSize) const {//................}AllocationOptions detachFlags() const {//................}AllocationOptions cloneFlags() const {//................}Q_REQUIRED_RESULT static QArrayData *allocate(size_t objectSize, size_t alignment,size_t capacity, AllocationOptions options Default) noexcept;Q_REQUIRED_RESULT static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize,size_t newCapacity, AllocationOptions newOptions Default) noexcept;static void deallocate(QArrayData *data, size_t objectSize,size_t alignment) noexcept;static const QArrayData shared_null[2];static QArrayData *sharedNull() noexcept { return const_castQArrayData*(shared_null); }
};通过QChar或者char实例化一个QString对象时调用allocate函数内部调用了malloc分配内存并将QArrayData指针对象header指向该内存初始化标头数据并返回header赋值给指针d。
QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,size_t capacity, AllocationOptions options) noexcept
{//..............QArrayData *header static_castQArrayData *(::malloc(allocSize));if (header) {quintptr data (quintptr(header) sizeof(QArrayData) alignment - 1) ~(alignment - 1);#if !defined(QT_NO_UNSHARABLE_CONTAINERS)header-ref.atomic.storeRelaxed(bool(!(options Unsharable)));
#elseheader-ref.atomic.storeRelaxed(1);
#endifheader-size 0;header-alloc capacity;header-capacityReserved bool(options CapacityReserved);header-offset data - quintptr(header);}return header;
}QLatin1String
如果没有定义QT_NO_CAST_FROM_ASCII和QT_RESTRICTED_CAST_FROM_ASCII两个宏在QString中会定义一系列以const char*为参数的函数比如拷贝构造函数和拷贝赋值运算符支持QString和字符串常量的转换和比较。而如果定义了该宏类似 QString dd example和dd example 的操作是不能通过编译的因为相关函数将失效并且定义QT_NO_CAST_FROM_ASCII后将几个函数定义成私有的。 Qt提供了QLatin1String类来更高效的利用const char*的类型dd example转换成dd QLatin1String(example) 虽然在代码输入的时候有点长但是两者效率差不多同时也比使用QString::fromLatin1()转换更快。
class QLatin1String
{
public:Q_DECL_CONSTEXPR inline QLatin1String() noexcept : m_size(0), m_data(nullptr) {}Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) noexcept : m_size(s ? int(strlen(s)) : 0), m_data(s) {}Q_DECL_CONSTEXPR explicit QLatin1String(const char *f, const char *l): QLatin1String(f, int(l - f)) {}Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) noexcept : m_size(sz), m_data(s) {}inline explicit QLatin1String(const QByteArray s) noexcept : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}Q_DECL_CONSTEXPR const char *latin1() const noexcept { return m_data; }Q_DECL_CONSTEXPR int size() const noexcept { return m_size; }Q_DECL_CONSTEXPR const char *data() const noexcept { return m_data; }//字符串操作//类型别名
private:int m_size;const char *m_data;
};QStringLiteral
在编译时构造QString对象适用于只能接受QString参数的场景转换后的字符串数据存储在编译后文件的只读数据段中使用时读取。接受const char *或QLatin1String直接使用比该宏更高效。
乱码
const char *字符默认UTF-8编码QString采用UTF-16编码。根据源文件相应格式解码后Windows环境下可执行文件中的字符串是本地编码格式GBK编码运行时以UTF-8解码再进行UTF-16编码就会出现乱码。 解决方法 1、解码QStringLiteral()宏或者QString::fromLocal8Bit()封装字符串 2、编码编译器采用UTF-8编码生成可执行文件
#if _MSC_VER 1600
#pragma execution_character_set(utf-8)
#endifQStringRef
QStringRef 提供 API 的只读子集。此类旨在提高操作从现有实例获取的子字符串时子字符串处理的性能。QStringRef 通过简单地引用原始字符串的一部分来避免标准的内存分配和引用计数开销修改字符串操作如mid、left、right等会创建一个新的字符串申请空间并拷贝数据。这在低级代码例如解析器中使用的代码中可能被证明是有利的但代价是可能更复杂的代码。
对于大多数用户来说使用 QStringRef 而不是 QStringRef 没有语义上的好处因为 QStringRef 需要注意内存管理问题这可能会使代码的编写和维护更加复杂。
class Q_CORE_EXPORT QStringRef {const QString *m_string;int m_position;int m_size;
public:inline QStringRef(const QString *string, int position, int size);//............
};