【C++系列】指针对象和对象指针的区别
在 ListNode dummy(0);ListNode* cur = &dummy;
中,&
是取地址运算符,用来获取变量 dummy
的地址。具体如下:
ListNode dummy(0);
:创建了一个类型为ListNode
的对象dummy
,其值初始化为0
。&dummy
:取dummy
对象的地址。&
运算符用于获取变量的内存地址。ListNode* cur = &dummy;
:声明了一个指向ListNode
类型的指针cur
,并将其初始化为指向dummy
的地址。
在 ListNode* dummy = new ListNode(0); ListNode* cur = dummy;
中,dummy
是链表指针。具体如下:
ListNode* dummy = new ListNode(0);
:创建了一个类型为ListNode*
的链表指针dummy
,其值初始化为ListNode(0)
。new ListNode(0)
:实例化一个ListNode(0)
对象。ListNode* cur = dummy;
:声明了一个ListNode
类型的指针cur
,并将其初始化为dummy
指针。
为什么使用 &dummy
?
使用 &dummy
主要是为了简化链表的操作。具体来说:
-
简化链表操作:
dummy
是一个虚拟头节点,它的存在使得我们不必处理链表头部的特殊情况(比如在空链表上插入第一个节点,或者在链表头部插入新节点)。- 通过使用
dummy
,所有插入操作都可以统一处理,不需要额外的条件判断。
-
指针操作:
cur
是一个指针,用于遍历和构建新链表。- 将
cur
初始化为dummy
的地址,这样在向链表中添加第一个节点时,dummy.next
可以直接指向新节点,并且后续操作都可以通过更新cur
来进行。
区别
-
内存分配方式:
ListNode dummy(0);
是在栈上分配的内存。栈上的内存会在超出作用域时自动释放。ListNode* dummy = new ListNode(0);
是在堆上分配的内存。堆上的内存不会自动释放,需要手动调用delete
来释放,防止内存泄漏。
-
指针的使用:
ListNode dummy(0); ListNode* cur = &dummy;
这里dummy
是一个对象,cur
是指向dummy
的指针。ListNode* dummy = new ListNode(0); ListNode* cur = dummy;
这里dummy
本身就是一个指针,指向堆上的ListNode
对象,cur
也指向同一个对象。
优缺点
在栈上分配内存
优点:
- 自动管理内存:函数退出时,栈上的内存会自动释放,无需手动管理。
- 更快的内存分配和释放:栈上的内存操作通常比堆上的快。
缺点:
- 生命周期受限:栈上的对象在函数返回后就被释放,不适合需要在函数外部长期使用的对象。
在堆上分配内存
优点:
- 生命周期灵活:可以手动控制对象的生命周期,适合需要在函数外部长期使用的对象。
缺点:
- 手动管理内存:需要手动释放内存,否则会导致内存泄漏。
- 相对较慢的内存分配和释放:堆上的内存操作通常比栈上的慢。
在 C++ 中,.
和 ->
操作符用于访问对象的成员:
.
操作符用于直接访问对象的成员。->
操作符用于通过指针访问对象的成员。
区别
dummy.next
:dummy
是一个对象,通过.
操作符直接访问dummy
的成员next
。dummy->next
:dummy
是一个指向对象的指针,通过->
操作符访问指针指向的对象的成员next
。
具体示例
栈上分配对象
ListNode dummy(0); // dummy 是一个对象
ListNode* cur = &dummy; // cur 是指向 dummy 的指针
cur->next = new ListNode(1); // 通过 cur 指针访问 next 成员
ListNode* head = dummy.next; // 直接通过对象 dummy 访问 next 成员
在这个例子中:
dummy
是一个ListNode
对象,可以直接使用dummy.next
访问其成员。cur
是一个指向dummy
的指针,使用cur->next
访问dummy
的成员。
堆上分配对象
ListNode* dummy = new ListNode(0); // dummy 是一个指向 ListNode 对象的指针
ListNode* cur = dummy; // cur 和 dummy 都是指向同一对象的指针
cur->next = new ListNode(1); // 通过 cur 指针访问 next 成员
ListNode* head = dummy->next; // 通过 dummy 指针访问 next 成员
在这个例子中:
dummy
是一个指向ListNode
对象的指针,需要使用dummy->next
访问其成员。cur
同样是一个指向ListNode
对象的指针,使用cur->next
访问其成员。
总结
在使用栈上分配的对象时,使用 .
操作符访问成员,因为我们直接处理的是对象本身。而在使用堆上分配的对象时,使用 ->
操作符访问成员,因为我们处理的是指向对象的指针。