如何从std :: optional <qbytearray>中获取QByteArray并保留std :: nullopt而无需其他malloc?

时间:2018-07-18 11:24:52

标签: c++ qt c++17

我需要编写一个函数,该函数具有optional<QByteArray>的基础数组的所有权。

在Rust中,它是通过以下方式完成的:

fn my_func(f: &mut Option<Box<[u8]>>) -> Box<[u8]> {
     //how to do "take" in c++17?
     f.take().unwrap()
}

我了解std::move,但是据我所知,这段代码将malloc的数据用于新数组,交换指针并丢弃不需要的QByteArray

std::optional<QByteArray> optarr = ...
QByteArray optarr = std::move(*myopt);
optarr.reset()

在Rust中,有什么方法可以做到这一点(也就是说,不为临时QByteArray分配内存)吗?

2 个答案:

答案 0 :(得分:6)

您对std::move的假设是错误的。粗略地说,std :: move强制转换为右值引用,因此本身不会生成任何实际代码。下一行将通过调用其移动构造函数在堆栈上创建一个QByteArray

QByteArray optarr = std::move(*myopt);

move构造函数从另一个QByteArray初始化Data指针,并将另一个的数据指针替换为指向共享空数据的指针。不涉及malloc,仅涉及两个指针分配。

move构造函数的implementation看起来像这样:

inline QByteArray(QByteArray && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }

所以您的代码实际上正在执行您想要的操作。

答案 1 :(得分:5)

C ++中等效的函数为:

auto func(optional<QByteArray>&& o) -> QByteArray
{
    return std::move(o).value();
}

std::move(o)为您提供类型optional<QByteArray>的右值。在该右值上调用value()会给您QByteArray&&(如果o脱离则抛出)。类型QByteArray的右值用于移动构造返回对象。这种移动结构很便宜,只需分配一些指针-不会发生内存分配。


几乎等效。请注意,o not 最终不会成为脱离的optional,与Rust不同。它仍然处于活动状态,只是持有一个空的QByteArray。如果确实需要,则真正等效的是:

auto func(optional<QByteArray>&& o) -> QByteArray
{
    QByteArray result = std::move(o).value(); // NB: not a reference
    o.reset();                                // or '= nullopt', or '= {}'
    return result;                            // NB: no need to move
}