Является ли возврат по rvalue ссылкой более эффективным? - PullRequest
116 голосов
/ 12 июля 2009

например:

Beta_ab&&
Beta::toAB() const {
    return move(Beta_ab(1, 1));
}

Ответы [ 2 ]

208 голосов
/ 12 июля 2009
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 не является ни локальным автоматическим, ни временным значением. Теперь ref-qualifier && говорит, что вторая функция вызывается для временных значений rvalue, делая следующий шаг вместо копии

Beta_ab ab = Beta().getAB();
3 голосов
/ 09 апреля 2018

Это может быть более эффективным, например, в несколько ином контексте:

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.

...