Вопрос по Call-By-Reference? - PullRequest
       11

Вопрос по Call-By-Reference?

1 голос
/ 15 февраля 2010

main () вызывает функцию Call_By_Test () с параметром аргумента Первый узел. Я освободил первый узел в Call_By_Test (), но адрес первого узла не освобожден в main (), почему?.

typedef struct LinkList{
int data;
struct LinkList *next;
}mynode;

void Call_By_Test(mynode * first)
{
        free(first->next);
        first->next = (mynode *)NULL;
        free(first);
        first = (mynode *)NULL;
}
int main()
{
mynode *first;

first = (mynode *)malloc(sizeof(mynode));
first->data = 10;
first->next = (mynode *)NULL;

cout<<"\n first pointer value before free"<<first<<endl;

Call_By_Test(first);
// we freed first pointer in Call_By_Test(), it should be NULL
if(first != NULL)
        cout<< " I have freed first NODE in Call-By-Test(), but  why first node pointer has the value "<<first<<endl;


}

Выход: первое значение указателя 0x804b008 Я освободил первый узел в Call-By-Test (), но почему указатель первого узла имеет значение 0x804b008

Ответы [ 5 ]

7 голосов
/ 15 февраля 2010

Ответ в том, что вы не используете передачу по ссылке. Вы передаете указатель по значению - и это не одно и то же. Это означает, что вы увидите изменения в данных, на которые ссылается указатель, но изменение значения first в методе Call_By_Test ничего не дает.

5 голосов
/ 15 февраля 2010

Поскольку вопрос помечен c ++, я бы изменил рефакторинг на:

void Call_By_Test( mynode *& first ) // rest of code remains the same

Это передает передачу по ссылке без дополнительных разыменований. Все решения, которые предлагают передавать указатель на указатель (void Call_By_Test( mynode ** first )), используют семантику передачи по значению в указателе на переменную указателя. Хотя вы можете сделать это в C ++, передача по ссылке более понятна.

3 голосов
/ 15 февраля 2010

В функции

void Call_By_Test(mynode * first)

first - это локальная переменная функции. Изменение его не изменит состояние остальной части программы. Вам нужна ссылка на указатель или указатель на указатель:

void Call_By_Test(mynode ** first)
{
        free((*first)->next);
        (*first)->next = NULL;
        free(*first);
        *first = NULL;
}

и назвать его:

Call_By_Test( & first );
1 голос
/ 15 февраля 2010

Когда вы делаете:

void Call_By_Test(mynode * first)

Сначала вы копируете, так что вы можете работать с тем, что находится первым, но вы не можете сначала изменить адрес, так как это копия.

Если вы хотите сначала изменить значение, тогда у вас должна быть такая функция:

void Call_By_Test(mynode ** first)

или

void Call_By_Test(mynode & first)

, который позволяет вам сначала получить доступ к аргументу, как если бы он был исходной переменной (а не копией из основной функции)

0 голосов
/ 15 февраля 2010

Если вы free указатель (например, 0x804b008), это не меняет биты в самом указателе. Это просто позволяет библиотеке C ++ записывать, что память по указанному адресу больше не используется, и ее можно использовать повторно. В вашем случае, когда вы печатаете 0x804b008, память по адресу 0x804b008 доступна для повторного использования библиотекой C ++.

...