如何从std :: optional <QByteArray>获取QByteArray并离开std :: nullopt而不需要额外的mallocs?

cha*_*pok 3 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()
}
Run Code Online (Sandbox Code Playgroud)

我知道std::move,但据我所知,这段代码将为malloc新数组,交换指针和删除不需要的数据QByteArray:

std::optional<QByteArray> optarr = ...
QByteArray optarr = std::move(*myopt);
optarr.reset()
Run Code Online (Sandbox Code Playgroud)

有没有办法和Rust一样(也就是说,没有为临时分配内存QByteArray)?

Pau*_*ulR 6

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

QByteArray optarr = std::move(*myopt);
Run Code Online (Sandbox Code Playgroud)

移动构造函数Data从另一个QByteArray 初始化指针,并用指向共享空数据的指针替换另一个数据指针.没有malloc涉及,只有两个指针分配.

move构造函数的实现如下所示:

inline QByteArray(QByteArray && other) Q_DECL_NOTHROW : d(other.d) { other.d = Data::sharedNull(); }
Run Code Online (Sandbox Code Playgroud)

所以你的代码实际上正在做你想要的.


Bar*_*rry 6

C++中的等效函数是:

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

std::move(o)给你一个类型的右值optional<QByteArray>.调用value()该右值会给你一个QByteArray&&(如果o被释放则抛出).该rvalue类型QByteArray用于移动构造返回对象.这种移动结构很便宜,只需几个指针分配 - 不会发生内存分配.


几乎相当于.请注意,o这里并没有结束的分离optional,与生锈.它还在忙着,只是空着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
}
Run Code Online (Sandbox Code Playgroud)