2015-12-09 2 views
0

Я написал следующий фрагмент кода. У меня вопрос: в этих двух линиях:путаница о указателе структуры C++

r1 = r; 
r1 = new node(); 

Я думаю, что когда r1 становится новым пустым узлом, r должен быть новым пустым узлом, поскольку r1=r является назначением указателя, так r1 и r представляет то же самое адрес. Однако я должен ошибаться, потому что результат показывает, что r здесь не был изменен. Может ли кто-нибудь объяснить это мне, почему r не изменен? Спасибо.

#include<iostream> 

using namespace std; 

struct node{ 
    int id; 
    node *child; 
}; 


int main() 
{ 
    node *r = new node(); 
    node *r1 = new node(); 
    r->id = 100; 

    r1 = r; 
    r1 = new node(); 
    r1->child = r; 

    cout << "r1 " << r1->id << endl; 
    cout << "r1 child " << (r1->child)->id << endl; 
} 

Результат:

r1 0 
r1 child 100 
+2

Два указателя могут указывать на одно и то же, но все равно быть разными указателями. – aschepler

+0

'r1 = r;' 'r1 = new node();' Итак ... 'r1' - это новый узел. Вывод вполне ожидаемый. – Ternvein

ответ

2

Указатель - это именно то, что указатель - он указывает (означает) что-то еще.

Я думаю, что в этом случае, возможно, легче всего понять вещи графически. Итак, после того, как вы делаете:

node *r = new node(); 
node *r1 = new node(); 
r->id = 100; 

Ситуация примерно так:

enter image description here

Тогда при выполнении: r1 = r;, вы получите такую ​​ситуацию:

enter image description here

Обратите внимание, что у вас есть утечка node, что r1 был pointi (т. е. у вас больше нет указателя на него, поэтому вы больше не можете его удалять).

Тогда, когда вы делаете r1 = new node();: вы получите что-то вроде этого:

enter image description here

Наконец, после выполнения r1->child = r; у вас есть что-то вроде этого:

enter image description here

0

Они не могут быть одинаковыми. r и r1 - это два местоположения в памяти, которые могут содержать адрес node (по определению в коде), поэтому при выполнении r1 = r значение в этих ячейках памяти становится таким же (значение указателя).

Но, когда вы позже выполните r1 = new node;, тогда new возвращает указатель на вновь созданный объект, который хранится только в ячейке памяти r1. Поскольку адрес в r местоположение в памяти не изменяется, значит, вы видите результаты.

0

У меня есть вопрос: в этих двух линиях: r1 = r;r1 = new node(); Я думаю, что когда r1 становится новым пустым узлом, r должен быть новым пустым узлом, поскольку r1=r является присвоением указателю

Не. Когда вы делаете r1 = r; все, что вы делаете, устанавливаете значение r1 на то же значение r. Он не связывает r1 и r вместе и все, что вы меняете в r1, ничего не делает для r.

Вы также должны заметить, что r1 = r; вызывает утечку памяти, так как r1 больше не указывает на узел, который вы изначально создали, и вы не сделали delete его перед назначением.

0

маршируют через шаг кода шаг за шагом может помочь объяснить, что происходит.

node *r = new node(); 

Создать блок памяти и точка r на

node *r1 = new node(); 

Создать блок памяти B и точка r1 на B

r->id = 100; 

Разница r, чтобы найти A. id в устанавливается на 100

r1 = r; 

Поинт r1 в то же самое, что r. r1 теперь указывает на A. Нет связи между A и B. Ничего не копируется из A - B. r1 просто перенаправляется в точку A вместо B.

B больше не имеет ссылок и утерян. Это называется утечкой памяти. delete r1; перед переназначением, чтобы предотвратить это. Лучше, так как B никогда не используется, не выделяйте его в первую очередь.

r1 = new node(); 

Создать блок памяти C и точки r1 на C. Как указано выше, r1 направляется в C вместо A. Никаких копий или других побочных эффектов не происходит. Связь между r1 и A. A не изменился и r по-прежнему указывает на A.

r1->child = r; 

разыменовывают r1 найти C.Точка child в C по адресу A.

cout << "r1 " << r1->id << endl; 

разыменовывают r1 найти C. Распечатка id в C. id в C никогда не назначалось значение, поэтому использование его - неопределенное поведение. Любое значение может быть напечатано, ничто не может быть напечатано, или программа может заставить компьютер расти ноги и есть кошку соседа, хотя это маловероятно.

cout << "r1 child " << (r1->child)->id << endl; 

разыменовывают r1 найти C. Разница child в C, чтобы найти A. Распечатка id в A, 100.