c++ - QByteArray 与 reserve() 的内部重新分配行为

标签 c++ qt memory-management qbytearray

我只是尝试优化一些通信堆栈。我正在使用 Qt 5.3.2/VS2013。

堆栈使用 QByteArray 作为数据缓冲区。我打算使用 capacity()reserve() 方法在数据大小增长时减少不必要的内部缓冲区重新分配。然而 QByteArray 的行为结果是不一致的。保留空间有时似乎被隐式压缩。

我可以提取以下演示,将字符串追加、字符串赋值和字符追加应用于三个缓冲区。这些单个操作似乎保留了内部缓冲区大小(使用 capacity() 获得)。但是,当将这三个操作中的每一个应用于同一个 QByteArray 时,保留的大小都会发生变化。这种行为在我看来是随机的:

QByteArray x1; x1.reserve(1000);
x1.append("test");
qDebug() << "x1" << x1.capacity() << x1;

QByteArray x2; x2.reserve(1000);
x2 = "test";
qDebug() << "x2" << x2.capacity() << x2;

QByteArray x3; x3.reserve(1000);
x3.append('t');
qDebug() << "x3" << x3.capacity() << x3;

QByteArray x4; x4.reserve(1000);
x4.append("test");
x4.append('t');
x4 = "test";
qDebug() << "x4" << x4.capacity() << x4;

预期的输出是:

x1 1000 "test"
x2 1000 "test"
x3 1000 "t"
x4 1000 "test"

但实际输出是:

x1 1000 "test"
x2 1000 "test"
x3 1000 "t"
x4 4 "test"

有人对这种奇怪的行为有解释吗?

更新:看起来 clear() 也丢弃了保留。

最佳答案

好的。我想我得到了我需要的信息。

显然,保留并不能在所有方法之外得到维护。特别是 clear()operator=() 似乎取消了保留。在 operator=() 的情况下,由于 operator=(QByteArray) 使用的数据隐式共享,实际上不可能保留保留。

这也意味着 QByteArray 的保留机制是为不同的用例制定的。尝试使保留在 QByteArray 对象的整个生命周期中持续存在是很困难的。

对于我的用例,似乎有一个使用 truncate(0) 而不是 clear()operator=() 的解决方法:

QByteArray buffer;
buffer.reserve(1000);
buffer.append("foo");
qDebug() << "buffer" << buffer.capacity() << buffer;

buffer.truncate(0);
buffer.append("bar");
qDebug() << "buffer" << buffer.capacity() << buffer;

这打印:

buffer 1000 "foo"
buffer 1000 "bar"

(感谢亚历杭德罗)

更稳定的方法是在每个数据收集/附加序列之前执行 reserve() 调用。这不会在 QByteArray 的整个 life 中将重新分配减少到一次,但至少它对每个数据序列只使用一次重新分配,否则它需要多次重新分配。我认为这是一个可以接受的解决方法。

无论如何,在 Qt 容器上使用 reserve() 之前,应该详细测试行为,否则容器的行为可能会与预期的大不相同。这一点也很重要,因为这些基本的实现细节没有记录在案,并且在未来的 Qt 版本中可能会更改,恕不另行通知。

关于c++ - QByteArray 与 reserve() 的内部重新分配行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26821207/

相关文章:

c++ - 使用 VTK 检查点是否在内部和对象

c++ - Qt 信号和槽发送结构数组

qt - qt中的java等效面板

iphone - _dyld_start 导致 iPhone 应用程序泄漏

c++ - 放大 WaveForm 音频的正确公式是什么?

c++ - 删除数组中的尾随零

c++ - 如何将一个整数与另外两个整数分开? C/C++

c++ - 在没有额外代码的情况下链接两个独立类的最通用方法是什么?

c++ - 删除堆上存储数据的堆上对象

c# - 如何查看给定 .NET 应用程序中的内存分配?