C++类实现链表报taking address of rvalue错误如何解决
报错原因
你遇到的报错核心是代码尝试获取右值(临时对象)的内存地址:
taking address of rvalue [-fpermissive] 31 | ListNode l = ListNode(2, &ListNode(4));
C中直接写ListNode(4)构造出的是临时对象,属于纯右值,它的生命周期仅持续到当前行表达式执行完毕,表达式结束后这个临时对象就会被系统自动销毁。如果把它的地址存到链表节点的next指针里,后续这个指针会变成悬空指针,指向已经被回收的无效内存,访问时会触发未定义行为(崩溃、脏数据等),因此编译器默认会直接拦截这种不合法的写法。
另外你用class实现链表和用struct实现没有本质区别,C中struct默认成员访问权限是public,class默认是private,你已经把ListNode的成员都声明为public了,用法和struct完全一致,这个报错和你用class还是struct没有关系。
正确实现方案
根据你需要的节点生命周期,选对应写法即可:
- 栈上静态分配:适合节点生命周期和当前作用域绑定的场景,不需要手动管理内存,注意被指向的节点要比持有它指针的节点先定义、后销毁
#include<iostream> class ListNode { public: int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; int main(){ // 先定义值为4的节点,它的生命周期贯穿整个main函数 ListNode node4(4); // 再定义头节点,传入node4的地址是合法的,因为node4在l之后才会被销毁 ListNode l(2, &node4); return 0; }
- 堆上动态分配:适合节点生命周期需要跨作用域的场景,需要手动管理内存,用完后要逐个delete节点避免内存泄漏
#include<iostream> class ListNode { public: int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; int main(){ // 在堆内存创建值为4的节点,生命周期直到手动调用delete才会结束 ListNode* node4 = new ListNode(4); ListNode l(2, node4); // 链表使用完毕后释放堆内存 delete node4; return 0; }
注意:不要通过加
-fpermissive编译选项强行绕过这个报错,临时对象销毁后指针指向的内存会被系统复用,后续访问会出现完全不可预期的错误。
内容的提问来源于stack exchange,提问作者Simon Rechermann
相关产品推荐
相关产品推荐

