简体   繁体   English

如何从std :: optional中获取QByteArray <QByteArray> 并且在没有额外的mallocs的情况下离开std :: nullopt?

[英]How to take QByteArray from std::optional<QByteArray> and leave std::nullopt without additional mallocs?

I need to write a function that takes ownership of an optional<QByteArray> 's underlying array. 我需要编写一个函数来获取optional<QByteArray>的底层数组的所有权。

In Rust, it is done by this way: 在Rust中,它是通过这种方式完成的:

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

I know about std::move , but as far as I understand, this code will malloc data for a new array, swap pointers, and drop unneeded QByteArray : 我知道std::move ,但据我了解,这段代码将为新数组的malloc数据,交换指针和删除不需要的QByteArray

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

Is there any way to do this as well as in Rust (that is, without allocating memory for temporary QByteArray )? 有没有办法和Rust一样(也就是说,没有为临时QByteArray分配内存)?

Your assumption about std::move is wrong. 你对std::move假设是错误的。 Roughly speaking std::move casts to an rvalue reference, no actual code is generated in itself by that. 粗略地说std :: move强制转换为右值引用,本身不会生成任何实际代码。 The following line will create a QByteArray on the stack by calling its move constructor. 以下行将通过调用其移动构造函数在堆栈上创建QByteArray

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

The move constructor initializes the Data pointer from the other QByteArray and replaces the other's data pointer with pointer to shared empty data. 移动构造函数从另一个QByteArray初始化Data指针,并用指向共享空数据的指针替换另一个数据指针。 No malloc is involved, just two pointer assignments. 不涉及malloc ,只有两个指针分配。

The implementation of the move constructor looks like this: move构造函数的实现如下所示:

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

So your code is actually doing what you want. 所以你的代码实际上正在做你想要的。

The equivalent function in C++ would be: C ++中的等效函数是:

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

std::move(o) gives you an rvalue of type optional<QByteArray> . std::move(o)为您提供了一个optional<QByteArray>类型的右值。 Invoking value() on that rvalue gives you a QByteArray&& (or throws if o is disengaged). 在该右值上调用value()会为您提供QByteArray&& (如果oQByteArray&& ,则抛出)。 That rvalue of type QByteArray is used to move construct the return object. QByteArray类型的右值用于移动构造返回对象。 This move construction is cheap, just a few pointer assignments - no memory allocation happens. 这种移动结构很便宜,只需几个指针分配 - 不会发生内存分配。


Almost equivalent. 几乎相当于。 Note that o here does not end up as a disengaged optional , unlike in Rust. 请注意, o不像Rust中那样最终作为一个脱离的optional It is still engaged, just holding an empty QByteArray . 它仍在使用,只是持有一个空的QByteArray Truly equivalent, if really desired, would be: 如果真的需要,真的相当于:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM