Является ли возврат по 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 References 101, в котором объясняется проблема и как (N)RVO взаимодействует с этим.
Ваш случай возврата ссылки на rvalue был бы хорошей идеей в других случаях. Представь, что у тебя есть getAB()
функция, которую вы часто вызываете на временной. Не оптимально, чтобы он возвращал постоянную ссылку для временных значений rvalue. Вы можете реализовать это так
struct Beta {
Beta_ab ab;
Beta_ab const& getAB() const& { return ab; }
Beta_ab && getAB() && { return move(ab); }
};
Обратите внимание, что move
в этом случае не является обязательным, потому что ab
не является ни локальным автоматическим, ни временным значением. Теперь реф-классификатор &&
говорит, что вторая функция вызывается для временных значений rvalue, делая следующий шаг вместо копии
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
,