繁体   English   中英

确保QByteArray拥有其内存(QByteArray :: fromRawData)

[英]Ensure a QByteArray owns its memory (QByteArray::fromRawData)

假设我们有一个功能商店

void store(const QByteArray& data);

该功能的工作是获取data并将其存储起来。 不幸的是,如果参数是使用QByteArray::fromRawData(ptr, size)创建的,那么这样做是不安全的,因为它及其所有副本都要求ptr保持有效。

因此, store没有选项禁止其调用者传入这样的数组,将data视为立体声中的const char*或强制使用detach强制复制。 所有这一切都不令人满意,特别是后者会损害性能,因为如果data在传递给store之前被COW复制,我们将进行不必要的深层复制。

QByteArray有一个private函数nulTerminated其实现似乎正是我想要的:如果它不拥有内存,它就是深拷贝。 如果它拥有内存,它只会返回*this

真的有两个问题

  • 是否有使用public设施的解决方法?

  • Qt文档提到ptr必须仅在返回值的生命周期及其任何副本中存活。 如果你说.right(.size()) ,它似乎不是副本,所以Qt需要根据文档制作一份深层副本。 但它真的这样做了吗?

看源(例如这里 ), ba.right(ba.size()); 实际上是简单的浅拷贝,几乎是无操作,所以这不是你的解决方案。 在任何情况下,依赖于没有文档支持的任何行为都有点不安全,在未来的Qt版本中可能会在没有通知的情况下进行更改。

话虽如此, QByteArray::detach()没有文档但公开。 它将对使用fromRawData()创建的数组执行深层复制,但不会对已经未共享的数据执行深度复制,我认为这不太可能改变。 示范:

QByteArray ba1 = QByteArray::fromRawData("foo", 4);
QByteArray ba2("foo");
qDebug() << (void*)ba1.constData() << (void*)ba2.constData();
ba1.detach(); ba2.detach();
qDebug() << (void*)ba1.constData() << (void*)ba2.constData();

以上输出例如:

0x804b960 0x93ebfd8
0x93d2170 0x93ebfd8

查看源代码, IS_RAW_DATA位于qbytearray.cpp文件中,我没有发现任何可以使用公共接口利用它的方法。 所以,做你想做的事似乎是不可能的,而detach()是你能得到的最接近的,即使QByteArray::squeeze()也不会分离原始数据。

这听起来更像是一个概念问题,而不是技术问题。

store()试图获取绝对所有权,但在QByteArray上“取得所有权”在概念上没有多大意义 副本可能与另一个副本共享其内存,或者它可能不共享,或者它可能是从原始数据创建的,因此隐藏的所有权问题在引擎盖下进行,整个类旨在隐藏这一点 整个隐式共享事物与现代显式所有权转移范式不完全吻合,而QByteArray通过提供原始数据工具使事情进一步复杂化。

如果可能的话,接受一个非隐式共享容器,该容器对其内容拥有绝对所有权(例如std :: string,这很容易通过rvalue用QByteArray :: toStdString()生成),迫使调用者复制,这将是最好的选项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM