向链表添加新节点时,为何函数需返回该节点才能正常工作?
链表添加节点的问题解析
问题场景与代码
节点类定义
class node{ public: int item; node* ptr_next; node(int new_item = 0, node* new_ptr_next = nullptr): item(new_item), ptr_next(new_ptr_next){} };
有返回值的append_node函数
//Adds a node to the end of the linked list. //by making the last node point to the new node node append_node(const int& item, node* ptr_entry_node){ node* ptr_last_node; node* ptr_current_node; //Finds Last Node In List ptr_current_node = ptr_entry_node; while (ptr_current_node->ptr_next != nullptr){ ptr_current_node = ptr_current_node->ptr_next; } ptr_last_node = ptr_current_node; //Instanciates a new node and makes the last node point to the new node node new_node(item); ptr_last_node->ptr_next = &new_node; return new_node; }
主函数
int main(){ //Creates a node for the beggining of the linked list. node entry_node; append_node(12,&entry_node); std::cout<<entry_node.item<<"\n"; std::cout<<entry_node.ptr_next->item<<"\n"; }
无返回值的append_node函数
void append_node(const int& item, node* ptr_entry_node){ //Exact same code but no "return new_node;" }
运行有返回值的版本时,输出符合预期:
0 12
但改成无返回值版本后,输出的第二个值变成随机垃圾值(比如-1108142424),每次运行结果都不一样。
问题根源:栈对象的生命周期
你在append_node里创建的new_node是栈上的局部对象,它的生命周期只限于函数执行期间:
- 当函数返回
node对象时,return new_node;会触发拷贝构造,把栈上的new_node复制一份到函数调用处的临时对象中。虽然你没接收这个返回值,但临时对象会在main函数当前语句结束前保持存在。此时你让链表指针指向的是栈上已销毁的new_node地址,但巧合的是临时对象的内容和原对象一致,且在执行cout时临时对象还没被销毁,所以能读到正确值——但这本质是未定义行为,只是刚好表现正常而已。 - 当函数改成
void返回时,函数执行完毕后栈上的new_node会被立即销毁,它占用的内存会被系统回收或重新分配。此时链表指针指向的是一块无效内存(野指针),读取这块内存的值自然是随机垃圾值。
换句话说,有返回值的版本能正常输出只是巧合,并不是正确的写法——链表指针指向了已经销毁的栈对象,后续任何操作都可能引发崩溃或错误。
正确写法:使用堆内存分配
要真正安全地添加节点,应该用new在堆上分配节点,这样对象的生命周期不受函数栈限制:
void append_node(const int& item, node* ptr_entry_node){ node* ptr_current_node = ptr_entry_node; // 遍历找到链表最后一个节点 while (ptr_current_node->ptr_next != nullptr){ ptr_current_node = ptr_current_node->ptr_next; } // 在堆上创建新节点,让最后一个节点的指针指向它 ptr_current_node->ptr_next = new node(item); }
这样新节点存储在堆中,函数执行完毕后不会被销毁,链表指针指向的是有效内存地址,读取item的值就会是正确的12。
注意:用new分配的内存需要在链表不再使用时,遍历链表逐个用delete释放,避免内存泄漏。
内容的提问来源于stack exchange,提问作者timmy george
相关产品推荐
相关产品推荐

