Является ли возврат по ссылке rvalue более эффективным?
например:
Beta_ab&&
Beta::toAB() const {
return move(Beta_ab(1, 1));
}
2 ответа:
Beta_ab&& Beta::toAB() const { return move(Beta_ab(1, 1)); }
это возвращает висячую ссылку, как и в случае ссылки lvalue. После возврата функции временный объект будет уничтожен. Вы должны вернуться
Beta_ab
по значению, как показано нижеBeta_ab Beta::toAB() const { return Beta_ab(1, 1); }
теперь он правильно перемещает временный
Beta_ab
объект в возвращаемое значение функции. Если компилятор может, он вообще избежит перемещения, используя RVO (оптимизация возвращаемого значения). Теперь вы можете сделать послеBeta_ab ab = others.toAB();
и он будет двигаться построить временный в
ab
, или сделать RVO, чтобы опустить выполнение перемещения или копирования в целом. Я рекомендую вам прочитать BoostCon09 Rvalue Ссылки 101 что объясняет этот вопрос, и как (N)RVO взаимодействует с этим.
ваш случай возврата ссылки rvalue был бы хорошей идеей в других случаях. Представьте, что у вас есть
getAB()
функция, которую вы часто вызываете на временной основе. Это не оптимально, чтобы он возвращал ссылку const lvalue для временных значений rvalue. Вы можете реализовать это такstruct Beta { Beta_ab ab; Beta_ab const& getAB() const& { return ab; } Beta_ab && getAB() && { return move(ab); } };
отметим, что
move
в этом случае не является обязательным, так какab
не является ни локальным автоматическим, ни временным значением rvalue. Теперь ref-квалификатор&&
говорит о том, что вторая функция вызывается на R-значения временных протезов, делая следующий шаг, вместо того, чтобы копироватьBeta_ab ab = Beta().getAB();
Это можете быть более эффективным, например, в несколько ином контексте:
template <typename T> T&& min_(T&& a, T &&b) { return std::move(a < b? a: b); } int main() { const std::string s = min_(std::string("A"), std::string("B")); fprintf(stderr, "min: %s\n", s.c_str()); return 0; }
как интересное наблюдение, на моей машине
clang++ -O3
генерирует 54 инструкции для кода выше против 62 инструкций для обычныхstd::min
. Однако, с-O0
Он генерирует 518 инструкций для кода выше по сравнению с 481 для обычныхstd::min
.