Как известно, возвращать локальную переменную из функции в C ++ небезопасно из-за области видимости.
В Effective C ++ Third Edition Скотт Мейерс рассказывает об этой проблеме в пункте 21 на странице 101. Однако в заключение он сказал, что правильным решением будет написать:
inline const Rational operator*(const Rational& lhs, const Rational& rhs) {
return Rational(lhs.n * rhs.h, lhs.d * rhs.d);
}
Разве это не плохая практика, и эта функция небезопасна?
UPD: Спасибо всем за объяснения.
Вы не можете на самом деле вернуть локальную переменную. Вы можете вернуть значение локальной переменной, или указатель на нее (т.е. ее адрес), или ссылка на нее.
Возвращение значение локальной переменной совершенно безопасно:
int good_func() {
int local = 42;
return local; // returns a copy of the value of "local"}
Возвращение указатель или же ссылка для локальной переменной небезопасно, потому что переменная перестает существовать, когда функция завершается:
int* bad_func() {
int local = 42;
return &local; // returns a pointer to "local"}
(То же самое относится к C, за исключением того, что C не имеет ссылок в стиле C ++.)
Возвращение локальной переменной из функции — это нормально и ничего плохого. возврате указатель или же ссылка Для локальной переменной это другая история, но в вашем примере нет ничего подобного.
Нет, это не небезопасно, потому что Rational
возвращается по значению. Это означает, что абонент получает копия из Rational
что вы создаете, что делает весь процесс безопасным.
Небезопасно возвращать ссылка к локальной переменной или для доступа через ссылку к объекту, который вышел из области видимости. Это не то, что происходит в примере кода.
Обратите внимание, что копия может быть создана без копирования, что может привести к снижению производительности. Это потому, что компиляторы C ++ могут использовать метод оптимизации возвращаемого значения описано здесь.
Нет, это небезопасно, вы возвращаете по значению, даже в C ++ 98 это безопасно, но в C ++ 98, возможно, не будет достаточно быстрым из-за дополнительной ненужной копии (использование Move Semantic в C ++ 11 позволяет избежать копирования ). Тем не менее, это не рекомендуется для большого объекта многими гуру C ++. Проблема с большими объектами заключается в том, что перемещение может перерасти в копию в некоторых элементах данных объекта.