Назначить возвращаемое значение из функции в ссылку С++?

Это вопрос из двух частей. Можно ли присвоить возвращаемое значение функции ссылке? Например,

Foo FuncBar()
{
    return Foo();
}

// some where else
Foo &myFoo = FuncBar();

Это нормально? Его понимание того, что FuncBar() возвращает объект Foo, и теперь myFoo является ссылкой на него.

Вторая часть вопроса. Это оптимизация? Так что если вы делаете это в цикле много времени, лучше делать

Foo &myFoo = FuncBar();

или

Foo myFoo = FuncBar();

И учитывать использование переменных, не будет использовать ref, требующие более медленных различий?

Ответ 1

Foo &myFoo = FuncBar();

Не компилируется. это должно быть:

const Foo &myFoo = FuncBar();

потому что FuncBar() возвращает временный объект (т.е. rvalue), и только lvalues ​​могут быть привязаны к ссылкам на не-const.

Безопасно ли это?

Да, это безопасно.

Стандарт С++ указывает, что привязка временного объекта к ссылке на const продлевает время жизни временного ресурса самой ссылки и, таким образом, позволяет избежать того, что в противном случае было бы общей ошибкой оборванных ссылок.


Foo myFoo = FuncBar();      

Является Инициализация копирования.
Он создает копию объекта, возвращаемого FuncBar(), а затем использует эту копию для инициализации myFoo. myFoo - отдельный объект после выполнения оператора.

const Foo &myFoo = FuncBar();

Привязывает временное значение, возвращенное FuncBar() к ссылке myFoo, обратите внимание, что myFoo является просто псевдонимом возвращаемого временного, а не отдельного объекта.

Ответ 2

Вы не "назначаете" ссылку, вы привязываетесь к ссылке.

Это верно только тогда, когда тип const, и контекст - это тот, где существует автоматическое продление срока службы временного.

В общем случае, когда Foo не является типом const, ваши примеры не должны компилироваться. К сожалению, они могут компилироваться с одним общим компилятором из-за языковых расширений, реализованных этим компилятором. Хорошая идея - попробовать примеры (а также обычный код!) С минимум двумя компиляторами.


EDIT: в качестве примера исследовательской работы перед отправкой вопроса вы должны были скомпилировать следующий (или очень похожий) с самым высоким уровнем предупреждения, по крайней мере с двумя компиляторами, с и без const.
struct Bar {};

#ifdef CONST
    typedef Bar const Foo;
#else
    typedef Bar Foo;
#endif

Foo FuncBar()
{
    return Foo();
}

int main()
{
    // som where else
    Foo &myFoo = FuncBar();
}

Если вы еще этого не сделали, это может быть хорошей идеей сделать это сейчас.