При возврате значений из функции в C ++ у нас есть копия elision и (Named) оптимизация возвращаемых значений, помогающая нам создавать более эффективный код. Короче, следующий код:
std::vector<int> make_vec_1(){
std::vector<int> v;
v.resize(1e6);
return v;
}
приводит к тихому перемещению или прямому построению в месте назначения возвращаемого значения вместо копии. Правила вокруг этого также означают, что явное перемещение возвращаемого объекта при возврате фактически предотвращает эти оптимизации.
std::vector<int> make_vec_2(){
std::vector<int> v;
v.resize(1e6);
return std::move(v); // BAD
}
Эта версия предотвращает RVO, как объяснено в «Скотте Мейерсе» Effective Modern C ++ , Item 25.
Мой вопрос: что происходит, когда тип возвращаемого значения отличается, но может быть сконструирован с помощью перемещения из одной или нескольких локальных переменных? Рассмотрим следующие функции, каждая из которых возвращает необязательный вектор:
std::optional<std::vector<int>> make_opt_vec_1(){
std::vector<int> v;
v.resize(1e6);
return v; // no move
}
std::optional<std::vector<int>> make_opt_vec_2(){
std::vector<int> v;
v.resize(1e6);
return std::move(v); // move
}
Что из этого верно? Сначала линия return std::move(v)
выглядит как красный флаг, но я также подозреваю, что это правильно. То же самое касается следующих двух функций, возвращающих пару векторов:
std::pair<std::vector<int>, std::vector<int>> make_vec_pair_1(){
std::vector<int> v1, v2;
v1.resize(1e6);
v2.resize(1e6);
return {v1, v2}; // no move
}
std::pair<std::vector<int>, std::vector<int>> make_vec_pair_2(){
std::vector<int> v1, v2;
v1.resize(1e6);
v2.resize(1e6);
return {std::move(v1), std::move(v2)}; // move
}
В этом случае, несмотря на то, что на первый взгляд это выглядит странно, я думаю, что лучше перейти на возвращаемое значение.
Правильно ли я понимаю, что лучше переходить к возвращаемому значению, когда типы различаются, но возвращаемое значение может быть сконструировано из локальной переменной (переменных), из которой перемещаются? Неужели я неправильно понял NRVO или есть какая-то другая оптимизация, которая у меня впереди?