尽管进行了相应的更正,为什么指向指针的指针与指针的处理方式不同
Why is a pointer to pointer treated differently than a pointer in spite of corresponding corrections
我正在尝试从双向链表中删除一个节点。函数 deleteNode() 将接收链表的头部和要删除的节点。但是,根据我是将要删除的节点作为指针还是指向指针的指针传递,代码的行为会有所不同(尽管在语法中进行了相应的更正)。
这是我的双向链表节点结构 -
struct DNode {
int val;
struct DNode* next;
struct DNode* prev;
DNode(int val) { //constructor
this->val = val;
next = NULL;
prev = NULL;
}
};
下面的代码工作得很好:
void deleteNode(struct DNode** head, struct DNode* deleteMe) {
//head is pointer to pointer, deleteMe is pointer
if(!(*head) || !deleteMe) {
cout<<"\nDeletion not possible";
return;
}
if(deleteMe->prev != NULL)
deleteMe->prev->next = deleteMe->next;
if(deleteMe->next != NULL)
deleteMe->next->prev = deleteMe->prev;
if(deleteMe == *head)
*head = deleteMe->next;
delete deleteMe;
}
对应的驱动代码-
/*at this point, I have pushed elements into the Linked List to make it 4->3->2->1, where 4 is
the head*/
deleteNode(&head, head);
deleteNode(&head, head->next);
deleteNode(&head, head->next);
但是,当我将两个参数作为指向指针的指针发送时,我在 运行 时遇到崩溃:
void deleteNode(struct DNode** head, struct DNode** deleteMe) {
if(!(*head) || !(*deleteMe)) {
cout<<"\nDeletion not possible";
return;
}
if((*deleteMe)->prev != NULL)
(*deleteMe)->prev->next = (*deleteMe)->next;
if((*deleteMe)->next != NULL)
(*deleteMe)->next->prev = (*deleteMe)->prev;
if(*deleteMe == *head)
*head = (*deleteMe)->next;
delete *deleteMe;
}
对应驱动代码:
/*at this point, I have pushed elements into the Linked List to make it 4->3->2->1, where 4 is
the head*/
deleteNode(&head, &head);
deleteNode(&head, &head->next);
deleteNode(&head, &head->next);
PS - 这不完全是删除的问题:
如果您在错误代码中注释行 delete *deleteMe,代码将 运行 但输出会不同。
工作代码的输出:3
注释删除行后错误代码的输出:3->1
在这里,当你传递 &head
和 &head
时,
if(*deleteMe == *head)
*head = (*deleteMe)->next;
*deleteMe
和*head
是同一个对象(你传入地址的那个对象),赋值后还是同一个对象
(即相当于*head = (*head)->next;
和*deleteMe = (*deleteMe)->next
。)
所以这个,
delete *deleteMe;
在这种情况下与 delete *head
相同,然后事情就开始了。
在第一种情况下,*head
和deleteMe
是不同的对象,因此分配给*head
不会影响deleteMe
。
作为示例,这就是发生的情况(“main_head”是 main
中的变量)。
当你进入函数时,出现这种情况:
head
|
v +---+ +---+
main_head---->| ---->| ----> ...
^ +---+ +---+
| ^
deleteMe |
(*deleteMe)->next
赋值后*head = (*deleteMe)->next
:
head +-------------+
| | |
| | v
v | +---+ +---+
main_head-+ | ---->| ----> ...
^ +---+ +---+
|
deleteMe
你可以看到 head
和 deleteMe
仍然指向 main
的 head
,那是你赋值的对象。
使用工作代码,您可以从这里开始:
head
|
v +---+ +---+
main_head---->| ---->| ----> ...
+---+ +---+
^ ^
| |
deleteMe deleteMe->next
最后是
head +-------------+
| | |
| | v
v | +---+ +---+
main_head-+ | ---->| ----> ...
+---+ +---+
^ ^
| |
deleteMe deleteMe->next
我正在尝试从双向链表中删除一个节点。函数 deleteNode() 将接收链表的头部和要删除的节点。但是,根据我是将要删除的节点作为指针还是指向指针的指针传递,代码的行为会有所不同(尽管在语法中进行了相应的更正)。
这是我的双向链表节点结构 -
struct DNode {
int val;
struct DNode* next;
struct DNode* prev;
DNode(int val) { //constructor
this->val = val;
next = NULL;
prev = NULL;
}
};
下面的代码工作得很好:
void deleteNode(struct DNode** head, struct DNode* deleteMe) {
//head is pointer to pointer, deleteMe is pointer
if(!(*head) || !deleteMe) {
cout<<"\nDeletion not possible";
return;
}
if(deleteMe->prev != NULL)
deleteMe->prev->next = deleteMe->next;
if(deleteMe->next != NULL)
deleteMe->next->prev = deleteMe->prev;
if(deleteMe == *head)
*head = deleteMe->next;
delete deleteMe;
}
对应的驱动代码-
/*at this point, I have pushed elements into the Linked List to make it 4->3->2->1, where 4 is
the head*/
deleteNode(&head, head);
deleteNode(&head, head->next);
deleteNode(&head, head->next);
但是,当我将两个参数作为指向指针的指针发送时,我在 运行 时遇到崩溃:
void deleteNode(struct DNode** head, struct DNode** deleteMe) {
if(!(*head) || !(*deleteMe)) {
cout<<"\nDeletion not possible";
return;
}
if((*deleteMe)->prev != NULL)
(*deleteMe)->prev->next = (*deleteMe)->next;
if((*deleteMe)->next != NULL)
(*deleteMe)->next->prev = (*deleteMe)->prev;
if(*deleteMe == *head)
*head = (*deleteMe)->next;
delete *deleteMe;
}
对应驱动代码:
/*at this point, I have pushed elements into the Linked List to make it 4->3->2->1, where 4 is
the head*/
deleteNode(&head, &head);
deleteNode(&head, &head->next);
deleteNode(&head, &head->next);
PS - 这不完全是删除的问题:
如果您在错误代码中注释行 delete *deleteMe,代码将 运行 但输出会不同。
工作代码的输出:3
注释删除行后错误代码的输出:3->1
在这里,当你传递 &head
和 &head
时,
if(*deleteMe == *head)
*head = (*deleteMe)->next;
*deleteMe
和*head
是同一个对象(你传入地址的那个对象),赋值后还是同一个对象
(即相当于*head = (*head)->next;
和*deleteMe = (*deleteMe)->next
。)
所以这个,
delete *deleteMe;
在这种情况下与 delete *head
相同,然后事情就开始了。
在第一种情况下,*head
和deleteMe
是不同的对象,因此分配给*head
不会影响deleteMe
。
作为示例,这就是发生的情况(“main_head”是 main
中的变量)。
当你进入函数时,出现这种情况:
head
|
v +---+ +---+
main_head---->| ---->| ----> ...
^ +---+ +---+
| ^
deleteMe |
(*deleteMe)->next
赋值后*head = (*deleteMe)->next
:
head +-------------+
| | |
| | v
v | +---+ +---+
main_head-+ | ---->| ----> ...
^ +---+ +---+
|
deleteMe
你可以看到 head
和 deleteMe
仍然指向 main
的 head
,那是你赋值的对象。
使用工作代码,您可以从这里开始:
head
|
v +---+ +---+
main_head---->| ---->| ----> ...
+---+ +---+
^ ^
| |
deleteMe deleteMe->next
最后是
head +-------------+
| | |
| | v
v | +---+ +---+
main_head-+ | ---->| ----> ...
+---+ +---+
^ ^
| |
deleteMe deleteMe->next