Почему std :: option :: value () & amp ;; возврат & amp ;?

У меня была ошибка во время выполнения, когда заменили некоторый код с помощью std :: option:

Старый код:

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

Новый код:

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

Это было непредсказуемо для меня.
Причина сбоя в том, что метод возвращает T&&,

Мой вопрос в каких случаях T&& может быть полезно, почему метод не возвращает T,

Полный код:

#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

Решение

Это незначительный недостаток дизайна, вызванный двумя конкурирующими потребностями.

Во-первых, избегая лишних ходов, а во-вторых, включив продление срока службы ссылки.

Эти два конкурируют в текущем C ++; Вы обычно не можете решить обе проблемы одновременно. Таким образом, вы увидите код, выполняющий одно или другое, совершенно случайно.

Я лично нахожу возвращение ссылки на rvalue, чтобы создать больше проблем, чем переход от объекта, который скоро будет уничтожен, но тех, кто стандартизировал std::optional не согласился.

Мое предпочтительное решение будет иметь другие недостатки.

Чтобы это исправить — чтобы не приходилось идти на эти компромиссы — нам потребуется сложное грязное переопределение того, как работает продление срока службы. Таким образом, мы должны жить с этими проблемами сейчас.

3

Другие решения

возврате T вынуждает двигаться, создает его, в то время как обратная ссылка (rvalue-) не требует затрат.

Предположим, что у вас есть

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

затем

getOptional().value()

будет делать несколько копий (RVO здесь не применяется, так как возвращает (перемещенный) член).

1

По вопросам рекламы [email protected]