2016年9月1日 星期四

動態陣列,注意事項與二維一次性宣告方法

動態陣列,注意事項與二維一次性宣告方法

tags:C++

delete 與 delete [] 差異

兩者都會呼叫解構函式,差別在於
後者只會呼叫開頭指標的解構函式
簡單來說今天你配置了arr[n]的動態陣列
如果你僅使用 delete 那只會解構 arr[0]
後面全部都不會被解到,可怕的是
這並不意味不能編譯與執行。
為了避免這種情況,記得養好習慣
聽起來很複雜,用一句話概括
方括配方括

這裡如果還不夠明白,簡單測試一下就能馬上了解了
#include <iostream>
class cls{
public:
    cls(){ std::cout << "constructor" << std::endl; }
    ~cls(){ std::cout << "destructor" << std::endl; }
};
int main(){
    cls* p = new cls[5];
    delete [] p;
    return 0;
}

釋放的指標最好手動指向空指標

上面我們可以知道 new[] 必須搭配 delete []
這裡還有一個小問題,你可以嘗試著把上方的代碼
印出釋放後的指標,你會發現指標沒有指向 0
這不是太大問題,但是如果造成問題了(肯定會有的
只是用到機率不大),應該不容易被找到問題點
養成習慣最好在釋放後手動指向空指標
空指標這裡簡單的敘述什麼該用什麼
  • C 使用 NULL
  • C++ 使用 0
  • c++11 使用 nullptr
千萬不要因為看起來不重要,且實際實際執行
時確實無法直接看出差別,就忽視了或偷懶

如果你不想 delete 那麼多

可以算出長度,一次宣告出全部
下標仍然可以使用,直接加上就好
void** new2d(int h, int w, int size){
    register int i;
    void **p;
    p = (void**)new char[h*sizeof(void*) + h*w*size];
    for(i = 0; i < h; i++)
        p[i] = ((char *)(p + h)) + i*w*size; 
    return p;
}
因此就可以用這 function 動態建立二維陣列
data = (int **)new2d(data_height, data_width, sizeof(int));

可以把他整合到Macro
在程式前頭增加
#define NEW2D(H, W, TYPE) (TYPE **)new2d(H, W, sizeof(TYPE))
便可簡化剛剛動態配置二維陣列寫法
data = NEW2D(data_height, data_width, int);

參考資料

  1. [問題] 指標 直接存取與使用下標存取 差異
    https://www.ptt.cc/bbs/C_and_CPP/M.1472632682.A.DE7.html
  2. 關於指標的new、delete、NULL的觀念問題
    http://www.programmer-club.com.tw/showSameTitleN/c/37427.html
  3. Re: [心得] 空指標常數(null pointer constant)
    https://www.ptt.cc/bbs/C_and_CPP/M.1461824349.A.B47.html

沒有留言:

張貼留言