Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

Anonymous
Anonymous asked in 電腦與網際網路程式設計 · 1 decade ago

關於C++的delete的觀念問題

最近在Linux底下練習寫C++,對於C++ delete的觀念有些不解,因此想請教一些問題,問題可能有點多請見諒:

曾經聽過有相對應的new就必須有相對應的delete,但是對於不同情形分配的空間哪些需要被delete掉不太了解,假設有以下幾種狀況:

Case 1:

class A{...};

void main(void)

{

A test1 = new A();

A *test2 = new A();

...

delete(test1);

delete(test2);

}

Case 2:

void main(void)

{

char test1[5] = {'H', 'E', 'L', 'L', 'O'};

char test2 = new char[5];

}

Case 3:

class A{

...

public:

int *Count()

{

int *test = new int[5];

return test;

}

};

void main(void)

{

int *a;

a = Count();

}

問題:

1. 一般的變數例如:int var=0;,像這樣的變數是不是不需要被delete?為什麼呢?

2. Case 1我想應該是確定得delete的,不過test1和test2這兩種宣告方式的空間分配有什麼差異嗎?

3. Case 2這兩個test1和test2哪個該被delete呢?是要用delete還是delete[]?

4. Case 3假設想刪掉Count()中test所分配的空間,是不是在main()裡面直接delete(a)就好?

5. 關於是否已將所有配置的空間都妥善的刪除掉,是必須由程式撰寫者自己去注意?還是有其他輔助工具可以檢查?

謝謝各位

1 Answer

Rating
  • ?
    Lv 7
    1 decade ago
    Favorite Answer

    Case 1:

    你不能寫

    A test1 = new A();

    因為 new A() 回傳的是一個 A *, compiler 會告訴你型態不符.

    如果硬要寫

    A test1 = *(new A());

    會 invoke A 的 copy constructor, 造成記憶體洩漏.

    你也不能寫

    delete test1;

    因為 delete 後面要接一個 new 出來的 pointer.

    你更不能寫

    delete &test1;

    因為 test1 是配置在 stack 上的自動變數, 不是 new 出來的 heap 變數.

    Case 2:

    你必須寫

    char * test2 = new char[5];

    Case 3:

    除非是在 factory method 中, 否則最好避免回傳 new 出來的 pointer, 因為很容易忘記 delete.

    例如你的 main() 中, 在用完 a 以後應該要多加一行

    delete a;

    所謂 "factory method" 是指專門用來生物件實體的函式, 詳情請參考 design pattern. 例如以下在某圖形處理函式庫中用來生成形狀的 factory:

    class Circle;

    class Triangle;

    class Rectangle;

    class ShapeFactory {

    public:

    Circle * makeCircle(double x, double y, double r);

    Triangle * makeTriangle(double x1, double y1, double x2, double y2, double x3, double y3);

    Rectangle * makeRectangle(double x1, double y1, double x2, double y2);

    };

    回答:

    1. 因為他們的生命週期都是程式在決定, 編譯器知道什麼時候該釋放他們, 所以不用程式設計師手動指定.

    - 函式中的自動變數, 在進入函式時配置空間, 函式 return 時釋放.

    - 函式中的靜態變數, 在程式啟動時配置空間, 第一次呼叫該函式時初始化, 程式結束時釋放.

    - 全域變數在程式啟動時配置空間與初始化, 程式結束時釋放.

    2. 請見上面的 Case 1 回答, 只有 test2 的寫法正確, test1 會編譯錯誤.

    3. test1 會自動被系統回收, 你要手動釋放 test2:

    delete [] test2;

    4. 是

    5. 是, 必須自己注意. C++ 本身沒有 GC 設施.

    至於輔助工具, 我只知道在 *nix 上有 valgrind, 其他 OS 不清楚.

    2011-04-14 08:41:57 補充:

    重看了一次你的問題, 發現你是在 linux 下寫 c++.

    那麼你可以用 valgrind 來抓 memory leak.

    記得編譯的時候要把 debug symbol 編進去.

Still have questions? Get your answers by asking now.