【问题标题】:Ensure a QByteArray owns its memory (QByteArray::fromRawData)确保 QByteArray 拥有它的内存 (QByteArray::fromRawData)
【发布时间】:2016-07-07 01:47:54
【问题描述】:

假设我们有一个函数存储

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 需要根据文档进行深层复制。但真的如此吗?

【问题讨论】:

    标签: c++ qt qbytearray


    【解决方案1】:

    查看源代码(例如here),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 macroqbytearray.cpp 文件中,我没有发现任何可以使用公共接口利用它的方法。所以,做你想做的似乎是不可能的,detach() 是你能得到的最接近的,即使QByteArray::squeeze() 也不会分离原始数据。

    【讨论】:

    • 但据我了解,它也会深拷贝QByteArray a("hello"); QByteArray b = a; b.detach();,这是不希望的。
    • 所以我想我需要使用私有访问黑客入侵它并调用 nulTerminate 函数。感谢您的努力
    【解决方案2】:

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

    store() 试图获得绝对所有权,但在 QByteArray 上“获得所有权”在概念上没有多大意义。一个副本可能与另一个共享它的内存,或者它可能不共享它,或者它可能是从原始数据创建的,所以在幕后有一个隐藏的所有权玩弄,整个类旨在向你隐藏这一点时间>。整个隐式共享通常与现代显式所有权转移范式不太吻合,并且 QByteArray 通过提供原始数据设施使事情进一步复杂化。

    如果可能,接受一个非隐式共享容器,该容器对其内容拥有绝对所有权(例如 std::string,它很容易通过 QByteArray::toStdString() 由右值生成),强制调用者复制,会是最好的选择。

    【讨论】:

      猜你喜欢
      • 2014-06-03
      • 2017-10-30
      • 2018-12-22
      • 2018-02-25
      • 2013-07-14
      • 2015-12-15
      • 2013-12-25
      • 2023-03-24
      • 2014-03-07
      相关资源
      最近更新 更多