Why std::optional::value() &&; return &&?

喜你入骨 提交于 2019-12-23 22:25:35

问题


I have had runtime error, when replaced some code by using std::optional:

Old code:

T getValue();
...
const auto& value = getValue();
value.get();

New code:

std::optional<T> getValue();
...
const auto& value = getValue().value();
value.get(); // Runtime error, crash 

It was unpredictable for me. The reason of crash is that the method returns T&&.

My question is in what cases T&& can be useful, why the method does not return a T.

Complete code:

#include <experimental/optional>
#include <iostream>
#include <memory>

struct Value {
    std::unique_ptr<int> a = std::make_unique<int>(5);
};

std::experimental::optional<Value> getValue() {
    Value v;
    return v;
}

int main() {
    const Value& value = getValue().value();
    std::cout << *value.a << std::endl;
    return 0;
}

回答1:


It is a minor design flaw caused by two competing needs.

First, avoiding extra moves, and second enabling reference lifetime extension.

These two compete in current C++; you usually cannot solve both problems at once. So you will see code doing one or the other, quite haphazardly.

I personally find returning an rvalue reference to generate more problems than moving from a soon to be destroyed object, but those who standardized std::optional disagreed.

My preferred solution would have other downsides.

To fix this—to not have to make these compromises—we would require a complex messy redefinition of how lifetime extension works. So we have to live with these problems for now.




回答2:


Returning T forces to move construct it, whereas returning (rvalue-)reference has no cost.

Let suppose that you have

std::optional<std::array<T, N>> getOptional();

then

getOptional().value()

would do several copies (RVO doesn't apply here as it would return a (moved) member).



来源:https://stackoverflow.com/questions/46219314/why-stdoptionalvalue-return

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!