項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 widget-area-1 尚未註冊或是沒有一個 view.php 檔案.
項目 search-input 尚未註冊或是沒有一個 view.php 檔案.

【Effective Modern C++ 閱讀筆記 #1】ch4 – Smart Pointers 前言, 什麼是 dangling pointer?

ch4 – Smart Pointers 前言

raw pointer 的缺點

1. 以 raw pointer 而言,我們不知道他指向的是 single object 還是 array (表示法相同)

都是 object*,我們沒有辦法直接區分出來。

但為了簡化例子,我們以下使用 int 代替,但就沒辦法舉例到 single-object 的 delete。

  • 以下是 int array 的宣告
int* p = new int[0]; // accessing p[0] or *p is undefined
delete[] p; // cleanup still required
  • 以下是 int pointer 的宣告
#include <iostream>

using namespace std;

int main(){ 
    int n = 1;
    int* p1 = &n;
    cout << *p1 << endl;

    int a[3] = {1, 2, 3};
    int* p2 = a;
    cout << p2[1] << endl;

    int* p3 = new int[5]; // accessing p[0] or *p is undefined
    cout << p3[1] << endl;
    p3[1] = 10;
    cout << p3[1] << endl;
    delete[] p3; // cleanup still required

    return 0;
}

p1, p2 沒有使用到 new, 單純的拿地址,我們不需要寫 delete,
p3 使用了 new 宣告了 int array 這個 object,
我們需要手動 delete p3

  • 結果

2. raw pointer 我們需要手動進行 destroy,換言之我們可能會忘記要 delete

這個很直覺,有 new,就必須要在另外寫一個 delete,
這就不是很方便。

3. raw pointer 可能會有專用的 destruction,我們也必須傳入

我們應該要使用 delete,或使用 dedicated (專用的) destruction,
這是我們必須決定的。

4. 與第一點相同的,raw pointer 我們在 delete 時,是 single-object 或是 array ?

與第一點相同的,raw pointer 我們在 delete 時,是 single-object 或是 array ?

  • single-object 要使用 delete
  • 而 array 要使用 delete[]

因為表示方法相同,所以我們沒辦法知道。

5. (未知的行為) raw pointer 因為手動 delete 的關係,我們可能會有不小心多次 delete 的情況

這其實比想像中容易發生,對於同一個物件的多次 delete,可能會有未知的行為。

obj* a;
if(condition){
    // Do something...
    delete a;
}
delete a;

我們不知道可能會發生什麼事。

6. (未知的行為) raw pointer 可能會創造出 dangling pointer,也不知道會發生什麼事

我們先來定義 dangling pointer,
通常我們會有一個 pointer 指向一個物件 (與其對應的記憶體位置)

pointer -> object(與對應的 memory 位置)

當 object 基於某些原因已經被 destroy,而這個仍然指向他的 pointer 就會被稱作 dangling pointer

dangling pointer -> 已 destroy object(對應的 memory 位置)

這個 pointer 依然指向這個記憶體位置,如果這時候我們使用了對這個 pointer 取值,
會發生什麼事情我們無法預期。

總結上述,我們發現 raw pointer 有太多細節需要注意
雖然稍加注意就可以防範,但我們必須非常謹慎使用才行

smart pointer 的出現

C++11 後,smart pointer 的出現,
基本上我們可以視為他是「原來 raw pointer 的 wrapper」,