[英]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.