全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1390
推到 Plurk!
推到 Facebook!

請教自定函式中傳回 new 的物件是否需 delete 的問題?

答題得分者是:yyu10
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-03-20 16:01:40 IP:219.137.xxx.xxx 未訂閱
依據各類與 C++ 有關的說明文件來看,凡是使用 new 指令來動態配置記憶體或產生的物件,都應該在使用完畢後將其 delete 掉,例如:
Graphics::TBitmap *Bitmap = new Graphics::TBitmap();    ... 處理過程 ....    delete Bitmap;
Bitmap = NULL;
那麼在自定函數中若要動態產生一些物件來做暫存處理,並將處理結果傳回時,例如:
Graphics::TBitmap* __fastcall TForm1::GetImage(void)
{
    Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap();        ... 處理過程 ....        return tmpBitmap;
}
在這個例子中 new 了一個 tmpBitmap,並要在處理過後將其傳回,因此並未在函數中將其 delete 掉,程式執行時並未發生問題,但是讓我產生了如下的疑惑,請先進們指導一下: 1. 如果上述自定函數的做法沒有問題,那麼為何在 new 之後卻又不用 delete 掉呢? 2. 如果上述作法不妥,那麼該如何處理才是正確的作法?
yyu10
中階會員


發表:9
回覆:99
積分:96
註冊:2005-02-18

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-03-20 16:46:51 IP:220.244.xxx.xxx 未訂閱
RedSnow, 你好    上述自定函數的做法沒有問題.
引言: 依據各類與 C 有關的說明文件來看,凡是使用 new 指令來動態配置記憶體或產生的物件,都應該在使用完畢後將其 delete 掉
这段话是对整个程式而言的, 不一定要在同一个自定函數用delete. 当你使用完處理結果以后, 要记住用delete把動態記憶體释放掉. 比如
 
Graphics::TBitmap *Bitmap;    Bitmap = GetImage();    ... 使用Bitmap ....    delete Bitmap;
Bitmap = NULL;
發表人 - yyu10 於 2005/03/20 16:51:19
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-03-21 00:17:33 IP:218.19.xxx.xxx 未訂閱
yyu10 您好:    您所舉的例子:
Graphics::TBitmap *Bitmap;    Bitmap = GetImage();    ... 使用Bitmap ....    delete Bitmap;
Bitmap = NULL;
這我是知道的,我所困惑的是例子中 GetImage 函數所 new 出來的那個 tmpBitmap,如果在 GetImage 函數中未將其 delete 掉的話,是否會有記憶體未被釋放的現象?還是說系統會在執行程序離開該函數之後,自動的將它清除掉? 發表人 - RedSnow 於 2005/03/21 00:19:13
yyu10
中階會員


發表:9
回覆:99
積分:96
註冊:2005-02-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-03-21 08:54:40 IP:203.14.xxx.xxx 未訂閱
系統不会自動清除 new 出來的記憶體. new 出來的記憶體会一直存在, 直到程式將其 delete 掉. 在 GetImage 函數中没有用 delete, 所以系統不會在離開該函數时自動的將它清除掉, 記憶體确实未被釋放. 但这并不是错误, 只要记着在程式其它地方將其 delete 掉就行了.
引言:
Graphics::TBitmap* __fastcall TForm1::GetImage(void)
{
    Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap();        ... 處理過程 ....        return tmpBitmap;
}
另外, GetImage 将得到的記憶體傳回, 表明程式其它地方还将用到这块記憶體, 因此不应该在 GetImage 中將其 delete 掉. 發表人 - yyu10 於 2005/03/21 09:02:01
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-03-21 17:19:18 IP:218.19.xxx.xxx 未訂閱
yyu10 您好:    我依據您的說明將我的問題整理成如下的例舉與解釋,請再幫我看看是否正確?
Graphics::TBitmap* __fastcall TForm1::GetImage(void)
{
    Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap();        ... 處理過程 ....        return tmpBitmap;
}    void __fastcall TForm1::SomeProc(void)
{
    Graphics::TBitmap *Bitmap = new Graphics::TBitmap();        Bitmap = GetImage();        ... 其它處理過程 ....        delete Bitmap;
    Bitmap = NULL;
}
1. 在 SomeProc 程序中 new 出來的 Bitmap 配置了一塊記憶體空間 A。 2. Bitmap 呼叫 GetImage 時,GetImage 函數中 new 出來的 tmpBitmap 亦配置了一塊記憶體空間 B。 3. 在 GetImage 程序結束時,將 tmpBitmap 所配置空間 B 的位址指標傳回。 4. 在 SomeProc 程序中 Bitmap 配置的空間位址重新指向 GetImage 函數所傳回的位址 B (原配置的記憶體 A 自動釋放掉?)。 5. 如果 Bitmap 呼叫了其它類似會傳回 TBitmap 指標的函數,則 Bitmap 配置的空間亦再度重新指向 (原配置的記憶體 B 自動釋放掉?)。 如果上述解釋是正確的,那麼現在就只剩下第 4 與第 5 項括號內的描述我還未能確認了,總之;在我的觀念裡,似乎範例中總有一處的記憶體是由系統 "自動釋放" 掉,或者是做了 "重新配置" 的動作,否則難以解釋 new 與 delete 未能匹配的狀況。
yyu10
中階會員


發表:9
回覆:99
積分:96
註冊:2005-02-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-03-21 18:37:46 IP:220.244.xxx.xxx 未訂閱
RedSnow, 您好,    简单的说, 您的例舉存在memory leak(記憶體未被釋放的現象).    您的解釋1, 2, 3是正确的.    
引言: 4. 在 SomeProc 程序中 Bitmap 配置的空間位址重新指向 GetImage 函數所傳回的位址 B (原配置的記憶體 A 自動釋放掉?)。
原配置的記憶體 A 没有釋放掉, 因为系统不会自動释放new出來的記憶體. 这需要写程式的人自己用delete来释放. 换句话说, 每一个new都应该有一个与之匹配的delete, 这样才不会引起memory leak. new和delete可以在同一函數中使用, 也可以分开. 你可以在函數A中用new得到一块記憶體, 然后在函數B中用delete将这块記憶體釋放掉. 您的例程需要改动一下,
Graphics::TBitmap* __fastcall TForm1::GetImage(void)
{
    Graphics::TBitmap *tmpBitmap = new Graphics::TBitmap();        ... 處理過程 ....        return tmpBitmap;
}    void __fastcall TForm1::SomeProc(void)
{
    Graphics::TBitmap *Bitmap = new Graphics::TBitmap();        ... 用到Bitmap(記憶體空間A)的處理過程 ....
    delete Bitmap; // delete 和上面的new匹配        Bitmap = GetImage();        ... 用到Bitmap(記憶體空間B)的處理過程 ....        delete Bitmap; // delete 和GetImage中的new匹配
    Bitmap = NULL;
}
 
發表人 - yyu10 於 2005/03/21 18:55:30
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-03-22 02:59:23 IP:218.19.xxx.xxx 未訂閱
yyu10 您好: 經您這麼說明之後,總算將我的疑惑解開了,我得依據現在的理解來將各個程式都再檢查一遍,以免造成記憶體的漏失。 多謝您不厭其煩的解說,祝您順心!
雲中鵝
一般會員


發表:14
回覆:24
積分:7
註冊:2004-12-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-05-24 22:04:57 IP:140.125.xxx.xxx 未訂閱
#include    using namespace std;    /*使副程式中,以new的元件來回傳值.*/    int* max(int &p,int &q)//pass by referred
{
int *i=new int(p);//test
int *j=new int(q);
if(*i>*j)
        return (i);
else
        return (j);
}    void main()
{
        int a=3,b=5;
        int *c=new int;
        c=max(a,b);//要和傳回的值相對應的形態
        *c=*c 10;
        cout<<*c<    請問大大....我剛才測了一下這個..但是這樣做不會就會使c的位址.沒有辨使用了嗎?沒辨法將原本c所配置的位址刪除了嗎?及為何把C的位址delete了,其內容仍沒有改變呢?而在副程式中的delete i,內容會改變呢?    謝謝回答    Try it!
        
------
Try it!
雲中鵝
一般會員


發表:14
回覆:24
積分:7
註冊:2004-12-21

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-05-24 22:06:52 IP:140.125.xxx.xxx 未訂閱
 int* max(int &p,int &q)//pass by referred
{
int *i=new int(p);//test
int *j=new int(q);
if(*i>*j)
{        delete j;
         return (i);
        }
else
{        delete i;
         return (j);}    //return (p>q ? &p : &q);
}
SORRY....副程式是這個 Try it!
------
Try it!
RedSnow
版主


發表:79
回覆:1322
積分:845
註冊:2003-12-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-05-24 23:20:35 IP:219.137.xxx.xxx 未訂閱
雲中鵝 您好: 本篇討論已結案,為了避免您的發問得不到適切的回覆,建議您另外新開一篇來發問,如果您的問題與本篇討論有關,或是需要參考到本篇,您可以將本篇連結列到您的發問文章中。
系統時間:2024-06-08 7:06:07
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!