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

QByteArray of zero size; where do begin() and end() point to?

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?始终构造适当的左值数组?

P.S。 API 按值返回 QByteArray 不是我的,它来自 QCanBusFrame->payload().

您在 std::copy 的呼叫中呼叫了 frame.getLoad() 两次。他们会 return 不同 QByteArray,所以他们的 begin()end() 没有关系。

你可以getLoad() return参考load来克服这个问题。

QByteArray& getLoad() { return load; }

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

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

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