零大小的 QByteArray; begin() 和 end() 指向哪里?

问题描述

QByteArray 使用写时复制策略,因此复制它们很便宜。我认为这也意味着可以按值传递它们。

然而,当我使用零长度的 QByteArray 时,这个假设似乎被打破了:

struct Frame 
{
  QByteArray load{0,0}; // zero size,fill with zeroes
  QByteArray getLoad() { return load; }
};

Frame frame;
std::copy( frame.getLoad().begin(),frame.getLoad().end(),<somewhere> );

这有时会产生 SEGFAULT,因为 begin()end() 似乎指向完全不同的位置,有时 end() 在数字上小于 begin()(这会触发调试验证检查MSVC 关于转置指针)。

我目前的理解是,这是因为 frame.getLoad() 构造了一个临时 QByteArray 两次,并且出于某种原因,其中的迭代器指向完全不同的位置 - 当且仅当数组大小为 0 时。 (如果数组大小为零并且实际上没有分配内存,我不确定他们应该指向哪里,但这对我来说仍然很令人惊讶)。

我的理解是否正确?如果是这样 - 我该怎么办?检查零大小的边缘情况?通过引用传递 QByteArray?总是构造合适的左值数组?

附言API 按值返回 QByteArray 不是我的,它来自 QCanBusFrame->payload()

解决方法

“Copy On Write”意味着它会在 write 之前copy。现在,当您调用 begin() 时,它会返回一个迭代器,您可以使用它写入到容器中而无需容器知道。那么,类应该怎么做才能避免(可能)使共享状态无效?它应该复制整个事情。这就是你的情况。您将获得 2 个副本,以及指向不同缓冲区的迭代器。

,

您在调用 frame.getLoad() 时调用了两次 std::copy。它们将返回不同的 QByteArray,因此它们的 begin()end() 没有关系。

您可以让 getLoad() 返回对 load 的引用来解决这个问题。

QByteArray& getLoad() { return load; }

如果您希望 getLoad() 返回 load 的副本,您应该在调用 std::copy 之前将其存储到一个变量中并使用它。

Frame frame;
QByteArray frameLoad = frame.getLoad();
std::copy( frameLoad.begin(),frameLoad.end(),<somewhere> );

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...