В общем, возврат ссылки совершенно нормален и происходит постоянно.
Если вы имеете в виду:
int& getInt() {
int i;
return i; // DON'T DO THIS.
}
Это все виды зла. Выделенный стек i
исчезнет, а вы ни на что не ссылаетесь. Это тоже зло:
int& getInt() {
int* i = new int;
return *i; // DON'T DO THIS.
}
Потому что теперь клиент должен в конечном итоге сделать странное:
int& myInt = getInt(); // note the &, we cannot lose this reference!
delete &myInt; // must delete...totally weird and evil
int oops = getInt();
delete &oops; // undefined behavior, we're wrongly deleting a copy, not the original
Обратите внимание, что ссылки на rvalue по-прежнему являются просто ссылками, поэтому все злые приложения остаются неизменными.
Если вы хотите выделить что-то, что выходит за рамки функции, используйте умный указатель (или вообще контейнер):
std::unique_ptr<int> getInt() {
return std::make_unique<int>(0);
}
А теперь клиент хранит умный указатель:
std::unique_ptr<int> x = getInt();
Ссылки также подходят для доступа к вещам, в которых вы знаете, что время жизни остается открытым на более высоком уровне, например ::
struct immutableint {
immutableint(int i) : i_(i) {}
const int& get() const { return i_; }
private:
int i_;
};
Здесь мы знаем, что можно возвращать ссылку на i_
, потому что все, что вызывает нас, управляет временем жизни экземпляра класса, поэтому i_
будет жить как минимум так долго.
И, конечно, в этом нет ничего плохого:
int getInt() {
return 0;
}
Если время жизни должно быть предоставлено вызывающей стороне, а вы просто вычисляете значение.
Резюме: нормально возвращать ссылку, если время жизни объекта не истечет после вызова.