Можно ли таким образом возвращать локальный указатель из функции?

В книге С. Прата наткнулся на пример:

struct free_throws {
     int made;
     int attempts;
     double percent;
};
const free_throws & clone(free_throws &ft) {
     free_throws *pt;
     pt = &ft;
     return *pt;
}

Насколько я понимаю нельзя возвращать локальные переменные по ссылке или по адресу, потому что они уничтожатся по окончанию функции и вернется ссылка на уже несуществующую переменную, т.е. на "мусор".

Вопрос: можно ли так возвращать локальную переменную-указатель? Почему?


Ответы (2 шт):

Автор решения: Harry

Давайте посмотрим, что у вас получается...

const free_throws & clone(free_throws &ft) {

Вы передаете функции ссылку на lvalue - на некий объект за пределами функции.

     free_throws *pt;
     pt = &ft;
     return *pt;

И по сути возвращаете его. Т.е. можно было просто написать -

     return ft;

Т.е. вы вернули ссылку на тот же объект, который и передали, только как на константный. Так что возвращать-то можно, а смысл?

Я тут - https://ideone.com/5fSQqc - немного упростил в смысле типов, и убрал константность - как видите, clone() возвращает просто то, что ей передали. Скажем так - никакого клонирования при этом не происходит.

Вот если бы вы сделали так:

const free_throws & clone(free_throws ft) {

это уже был бы возврат ссылки на локальную переменную (переданную в функцию копию) - тут дело другое.

→ Ссылка
Автор решения: Timur123

У вас по ссылке заходит объект и потом вы берете от него адрес. Это равносильно тому, что как будто вы не находясь в функции, а просто взяли адрес у объекта, не передавая его в функцию, так как ссылка это просто второе имя (псевдоним) на тот же самый объект. То есть внутри функции мы имеем дело с тем же самым объектом, что и существовал до того, как его передали в функцию. Поэтому взятие адреса внутри функции это тоже самое, что взятие адреса на него и вне функции. Потом вы разыменовываете этот указатель и попадаете на адрес объекта, то есть это равносильно тому, что вы просто бы обратились к объекту, что находится до захода в функцию. и потом возвращаете этот объект по ссылке наружу, то есть это равносильно тому, что вы и не пробрасывали вовсе объект в функцию, а просто создали ссылку на объект напрямую. Вы не вернули указатель или ссылку на локальную переменную, вы вернули ссылку на тот объект, что заходил в функцию сверху, то есть который существовал и до того, как вызвалась функция. Но есть один ньюанс. Если бы функция принимала бы константную ссылку (говоря более правильно - ссылку на константный объект), то вы могли бы тогда принять и временный объект (так как константная ссылка биндится к rvalue) и вот тогда возврат ссылки на него из функции был бы опасен, так как ссылка бы существовала после завершения функции, а временный объект, что заходил сверху в функцию к тому времени перестал бы существовать.

→ Ссылка