QT 容器类浅拷贝(隐式共享)问题初探

QT为了提升性能,好多容器类采用了写时复制,类似多引用共享一份数据,有必要的时候再拷贝。

通过代码实际验证来说明

#include <qdebug.h>
#include <QtCore/QCoreApplication>
#include <qvector.h>

QVector<int> createVector() {
	QVector<int> vec{ 1, 2, 3 };
	int* ptr0 = vec.data(); // 获取首元素指针
	*ptr0 = 20;
	qDebug() << *ptr0;

	return vec;  // 返回浅拷贝,共享数据
}
int main(int argc, char* argv[])
{
	QCoreApplication a(argc, argv);

	QVector<int> vecA = createVector();
	int* ptrA = vecA.data(); // 获取首元素指针
	qDebug() << *ptrA;

	QVector<int> vecB = vecA;  // 浅拷贝,共享数据
	int* ptrB0 = vecB.data(); // 获取首元素指针
	qDebug() << *ptrB0;

	vecB[0] = 10;              // 触发深拷贝,vecA 和 vecB 数据分离
	int* ptrB1 = vecB.data(); // 获取首元素指针
	qDebug() << *ptrB1;

	return a.exec();
}

1. 函数返回值为容器类时,实际上是浅拷贝,验证结果如下:

  • 子函数内数据的地址与返回值地址是相同的,类似“移动语义”
    在这里插入图片描述

2. QVector vecB = vecA; // 浅拷贝,共享数据

在这里插入图片描述

3. int* ptrB0 = vecB.data(); // 触发了拷贝

在这里插入图片描述

关于Qvector浅拷贝的常用操作

使用 mid()、left() 或 right() 截取子数组

  • QVector 的 mid()、left()、right() 方法默认会创建一个新的 QVector 实例,但底层数据会通过隐式共享机制与原数组共享同一内存块,直到修改时才触发深拷贝。
QVector<int> original = {1, 2, 3, 4, 5};
QVector<int> subVector = original.mid(1, 3); // 截取索引1开始的3个元素 [2,3,4]

// 此时 subVector 与 original 共享数据,未触发深拷贝
subVector[0] = 99; // 修改 subVector 会触发写时复制,分配独立内存

存储指针或轻量对象

  • 若元素本身需要避免深拷贝(如对象含指针成员),可将 QVector 存储为指针或轻量句柄,直接共享指针而非对象数据。
QVector<MyClass*> ptrVector;
ptrVector.append(new MyClass(1));
ptrVector.append(new MyClass(2));

// 截取指针(浅拷贝)
QVector<MyClass*> subPtrVector = ptrVector.mid(0, 2); // 共享指针,无对象复制

使用 QVector::fromRawData(谨慎使用)

  • 对于简单数据类型(如 int、double),可通过 QVector::fromRawData 直接引用原数组内存,实现零拷贝。但需注意:
  • ​数据必须连续​:原数组需为连续内存。
  • ​只读操作​:生成的 QVector 默认只读,若需修改需先调用 detach()(触发深拷贝)。
int rawData[] = {1, 2, 3, 4, 5};
QVector<int> rawVector = QVector<int>::fromRawData(rawData, 5); // 浅拷贝

// 修改前需分离数据(触发深拷贝)
if (!rawVector.isDetached()) {
    rawVector.detach(); // 强制深拷贝
}
rawVector[0] = 99; // 修改独立副本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HardBeans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值