【C++系列】指標物件和物件指標的區別

叶小知發表於2024-06-05

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 主要是為了簡化連結串列的操作。具體來說:

  1. 簡化連結串列操作

    • dummy 是一個虛擬頭節點,它的存在使得我們不必處理連結串列頭部的特殊情況(比如在空連結串列上插入第一個節點,或者在連結串列頭部插入新節點)。
    • 透過使用 dummy,所有插入操作都可以統一處理,不需要額外的條件判斷。
  2. 指標操作

    • cur 是一個指標,用於遍歷和構建新連結串列。
    • cur 初始化為 dummy 的地址,這樣在向連結串列中新增第一個節點時,dummy.next 可以直接指向新節點,並且後續操作都可以透過更新 cur 來進行。

區別

  1. 記憶體分配方式

    • ListNode dummy(0); 是在棧上分配的記憶體。棧上的記憶體會在超出作用域時自動釋放。
    • ListNode* dummy = new ListNode(0); 是在堆上分配的記憶體。堆上的記憶體不會自動釋放,需要手動呼叫 delete 來釋放,防止記憶體洩漏。
  2. 指標的使用

    • ListNode dummy(0); ListNode* cur = &dummy; 這裡 dummy 是一個物件,cur 是指向 dummy 的指標。
    • ListNode* dummy = new ListNode(0); ListNode* cur = dummy; 這裡 dummy 本身就是一個指標,指向堆上的 ListNode 物件,cur 也指向同一個物件。

優缺點

在棧上分配記憶體

優點

  • 自動管理記憶體:函式退出時,棧上的記憶體會自動釋放,無需手動管理。
  • 更快的記憶體分配和釋放:棧上的記憶體操作通常比堆上的快。

缺點

  • 生命週期受限:棧上的物件在函式返回後就被釋放,不適合需要在函式外部長期使用的物件。

在堆上分配記憶體

優點

  • 生命週期靈活:可以手動控制物件的生命週期,適合需要在函式外部長期使用的物件。

缺點

  • 手動管理記憶體:需要手動釋放記憶體,否則會導致記憶體洩漏。
  • 相對較慢的記憶體分配和釋放:堆上的記憶體操作通常比棧上的慢。

在 C++ 中,.-> 運算子用於訪問物件的成員:

  • . 運算子用於直接訪問物件的成員。
  • -> 運算子用於透過指標訪問物件的成員。

區別

  • dummy.nextdummy 是一個物件,透過 . 運算子直接訪問 dummy 的成員 next
  • dummy->nextdummy 是一個指向物件的指標,透過 -> 運算子訪問指標指向的物件的成員 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 訪問其成員。

總結

在使用棧上分配的物件時,使用 . 運算子訪問成員,因為我們直接處理的是物件本身。而在使用堆上分配的物件時,使用 -> 運算子訪問成員,因為我們處理的是指向物件的指標。

相關文章