Указатель - возврат локальной ссылки в C ++ - PullRequest
1 голос
/ 23 августа 2011

Я не уверен, задавался ли этот вопрос ранее (искал в SOF и не смог найти ответ)

Я написал класс LinkedList и функцию для его обратного.

    struct LinkedList::element* LinkedList::recurrsiveReverseList(element* head){
     element* tempList;
     if(head->next == NULL){
        return head;
     }else{
        tempList = recurrsiveReverseList(head->next);
        head->next->next = head;
        head->next = NULL;
        return tempList;        
    }
   }

здесь я объявляю переменную локального указателя и вносю в нее некоторые изменения и возвращаю ее обратно вызывающей стороне.В C ++, когда я объявляю локальную переменную внутри функции, область видимости существует только внутри функции.Теперь, когда я возвращаю указатель из функции, как это работает?Я могу понять логику и получить результат (к счастью), но я не в состоянии полностью понять работу здесь.

Может кто-нибудь очистить мои сомнения?

Ответы [ 5 ]

2 голосов
/ 23 августа 2011

Не уверен, что кто-то еще объяснил это таким образом, но сам указатель - не более чем число, например ... 0x12345678. Это число, в свою очередь, относится к позиции в памяти компьютера, которая содержит фактическое значение, которое вы ищете, который является узлом связанного списка.

Итак, когда вы возвращаете этот адрес, все в порядке, что исходная переменная была уничтожена. Например, скопировать адрес улицы на другой лист бумаги, а затем выбросить оригинал. Дом, который находится по адресу, который у вас есть, все еще там.

2 голосов
/ 23 августа 2011

Область действия tempList завершается при выходе из функции, но tempList является указателем на блок памяти, область действия которого не заканчивается там, потому что он, несомненно, был выделен new. Память, выделенная таким образом, действительна вплоть до того момента, когда вы delete ее используете, независимо от того, во сколько функций вы входите или выходите.

Передав указатель обратно вызывающей стороне, он сохраняет указатель в другом месте, где вы можете его использовать.

Простой пример:

static char *fn (void) {
    char *rv = new char[42];
    return rv;
}

int main (void) {
    char *x = fn();
    delete [] x;
    return 0;
}

В приведенном выше коде область действия rv ограничена функцией fn после ее объявления.

Область действия x ограничена функцией main после ее объявления.

Однако память, выделенная new, появляется в fn, а продолжает существовать после возвращения в main. Адрес указанной памяти, изначально сохраненный в rv, передается в x путем присвоения возвращаемого значения fn в x.

1 голос
/ 23 августа 2011

Указатель object tempList перестает существовать при выходе из функции. Но это нормально; вы возвращаете (копию) значения , которое было сохранено в объекте, а не в самом объекте. Это как

int n = 42;
return n;

(Возвращение адреса локальной переменной - вот что доставляет вам неприятности.)

0 голосов
/ 23 августа 2011

Область использования переменной tempList ограничена в методе как его локальный, но он содержит адрес памяти, который является тем, что возвращается. Код, который вызывает его, получит этот адрес памяти, а не переменную tempList.

0 голосов
/ 23 августа 2011

Я предполагаю, что узлы вашего связанного списка размещены в бесплатном хранилище (т.е. с new).

Когда вы создаете объект с new, он создается в бесплатном хранилище и существует до тех пор, пока вы не вызовете delete для него. Вы можете сделать столько указателей на это местоположение, сколько захотите, и оно существует независимо от каких-либо вызовов функций, в которых оно могло быть выполнено. Поэтому в этой функции вы просто возвращаете указатель по значению на это место в бесплатном хранилище. Указатель - это просто число, которое является адресом объекта, например, возвращает int по значению.

tl; dr: Вы, очевидно, знаете, что можете вернуть локальные объекты по значению, потому что копия сделана. В этой функции она возвращает копию указателя , которая указывает на местоположение в бесплатном хранилище, которое уничтожается только при вызове delete с указателем на эту ячейку памяти.

Как еще одно примечание, вам, вероятно, не следует возвращать указатель на новый заголовок списка, а вместо этого брать указатель на заголовок списка по ссылке и изменять список таким образом, чтобы, если кто-то забудет назначить свой старый заголовок указатель на тот, который возвращается recurrsiveReverseList, вещи не перепутаны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...