C++ 确保QByteArray拥有其内存(QByteArray::fromRawData)
假设我们有一个函数库C++ 确保QByteArray拥有其内存(QByteArray::fromRawData),c++,qt,qbytearray,C++,Qt,Qbytearray,假设我们有一个函数库 void store(const QByteArray& data); 此函数的任务是获取数据并将其存储起来。不幸的是,如果参数是使用QByteArray::fromRawData(ptr,size)创建的,那么这样做是不安全的,因为它及其所有副本都要求ptr保持有效 因此,store没有选项禁止其调用者传入这样的数组,将数据视为立体像上的常量字符*,或使用分离强制深度复制。所有这些都不令人满意,尤其是后者会影响性能,因为如果数据在传递到存储之前被复制,我们将进行
void store(const QByteArray& data);
此函数的任务是获取数据
并将其存储起来。不幸的是,如果参数是使用QByteArray::fromRawData(ptr,size)
创建的,那么这样做是不安全的,因为它及其所有副本都要求ptr
保持有效
因此,store
没有选项禁止其调用者传入这样的数组,将数据
视为立体像上的常量字符*
,或使用分离
强制深度复制。所有这些都不令人满意,尤其是后者会影响性能,因为如果数据
在传递到存储
之前被复制,我们将进行不必要的深度复制
QByteArray
有一个private
函数nulTerminated
,它的实现似乎正是我想要的:如果它不拥有内存,它会进行深度复制。如果它拥有内存,它只返回*this
真的有两个问题吗
- 使用
设施是否有变通办法公共
- Qt文档提到,
必须仅在返回值及其任何副本的生存期内处于活动状态。如果您说ptr
,这似乎不是一个副本,因此Qt需要根据文档制作一个深度副本。但它真的这样做了吗.right(.size())
查看源代码(例如),
ba.right(ba.size())
实际上是纯浅拷贝,几乎没有操作,所以这不是您的解决方案。而且在任何情况下,依赖没有文档支持的任何行为都有点不安全,在未来的Qt版本中可以在不通知的情况下进行更改
也就是说,它是无文件记录的,但是公开的。它将对使用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();
查看qbytearray.cpp文件中的源代码,我没有发现任何可以使用公共接口利用它的方法。因此,想做什么似乎是不可能的,而且
detach()
是最接近的,即使QByteArray::squeak()
不分离原始数据。这听起来更像是一个概念问题,而不是技术问题
store()
试图取得绝对所有权,但在QByteArray上“取得所有权”在概念上没有多大意义。一个副本可能与另一个共享内存,也可能不共享内存,或者它可能是从原始数据创建的,因此在后台存在一个隐藏的所有权把戏,整个类都是为了向您隐藏这一点而设计的。整个隐式共享与现代显式所有权转移范式总体上不匹配,QByteArray通过提供原始数据工具使问题进一步复杂化
如果可能的话,通过右值接受一个非隐式共享的容器,该容器对其内容拥有绝对所有权(例如std::string,它可以很容易地用QByteArray::toStdString()生成),强制调用方进行复制,这将是最好的选择。但据我所知,它还将深度复制
QByteArray a(“hello”);QByteArray b=a;b、 分离()代码>这是不需要的。所以我想我需要用私有访问黑客攻击它并调用nulTerminate函数。谢谢你的努力
0x804b960 0x93ebfd8
0x93d2170 0x93ebfd8