線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1273
推到 Plurk!
推到 Facebook!

該如何delete物件

尚未結案
benson5033
一般會員


發表:44
回覆:47
積分:18
註冊:2004-08-16

發送簡訊給我
#1 引用回覆 回覆 發表時間:2004-09-28 23:13:56 IP:218.167.xxx.xxx 未訂閱
我動態建立了物件 for(i=0;i<10;i ) { TButton test[i]=new TButton(this); test[i]=->Name="test" IntToStr(i); } 請問我要delete這些物件時,應該要怎麼做???? (搞了半天還是有問題)
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#2 引用回覆 回覆 發表時間:2004-09-28 23:48:06 IP:211.76.xxx.xxx 未訂閱
benson5033 您好:    您可參考下述連結的討論: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55815 不好意思!上面的討論是Delphi。 相對於您的問題,可以利用下列方式,釋放動態產生的物件,
for (int k=0; k<10; k  )
     { delete test[k];
       test[k] = NULL;
     }
RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====##### 發表人 - richtop 於 2004/09/28 23:55:14
benson5033
一般會員


發表:44
回覆:47
積分:18
註冊:2004-08-16

發送簡訊給我
#3 引用回覆 回覆 發表時間:2004-09-29 10:46:28 IP:61.230.xxx.xxx 未訂閱
引言: benson5033 您好: 您可參考下述連結的討論: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55815 不好意思!上面的討論是Delphi。 相對於您的問題,可以利用下列方式,釋放動態產生的物件,
for (int k=0; k<10; k  )
     { delete test[k];
       test[k] = NULL;
     }
RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====##### 發表人 - richtop 於 2004/09/28 23:55:14
可是我這樣做就一直出現"Access violation at address 32342E32.... 我也不知道為什麼???
andychang1690
資深會員


發表:20
回覆:694
積分:442
註冊:2003-03-14

發送簡訊給我
#4 引用回覆 回覆 發表時間:2004-09-29 11:05:57 IP:221.169.xxx.xxx 未訂閱
benson5033:參考一下;
.h檔
private:        // User declarations
或
public:                // User declarations
  TButton *test[10];
.cpp檔
void __fastcall TForm1::FormCreate(TObject *Sender)
{  
  for (int i=0; i < 10; i  ) {
    test[i] = new TButton(this);
    test[i]->Name="test" IntToStr(i);
  }
}
// Form的OnCloseQuery事件 
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  // 清除元件暫存檔
  for (int i = 0; i < 10; i  )  {
    delete test[i];
    test[i] = NULL;
  }
//或使用
//  delete [] test; // 是釋放全部
}    請參考!    
Andy Chang 發表人 - andychang1690 於 2004/09/29 11:07:50
------
Andy Chang
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#5 引用回覆 回覆 發表時間:2004-09-29 11:18:14 IP:211.76.xxx.xxx 未訂閱
benson5033 您好:    在之前就覺得有點怪怪的,但感覺您的程式碼不像是直接copy自BCB,而是手打的。不過這不重要了。 不知您的程式是否有在函式外部宣告:TButton *test[10];之類的?因為按照貼文上的程式碼來看,test[i]像是僅在for迴圈中有效的區域變數,所以當您在其他地方試圖要delete它時,就會有錯誤訊息發生。 底下修改建議,您先試試。如果還是有問題,恐怕得上傳整個程式來找出可能的問題點。 <>< face="Verdana, Arial, Helvetica">引言: 我動態建立了物件 for(i=0;i<10;i ) { TButton test[i]=new TButton(this); // 有點像是區域變數的宣告,設法在外部先宣告 test[i]->Name="test" IntToStr(i); delete test[i]; //先加入此行,改在此釋放物件,看會不會有同樣的錯誤發生 } 請問我要delete這些物件時,應該要怎麼做???? (搞了半天還是有問題) 修改的部分:TButton test[10]; => TButton *test[10]; RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====##### 發表人 - richtop 於 2004/09/29 22:08:38
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#6 引用回覆 回覆 發表時間:2004-09-29 13:04:31 IP:140.112.xxx.xxx 未訂閱
引言: 1.test[i]->Name="test" IntToStr(i); 2.delete [] test; // 是釋放全部 發表人 - andychang1690 於 2004/09/29 11:07:50
關於andychang1690版友的回應,我有些想討論的地方: 第一個碼是在執行期改變了元件的名稱,我記得好像BCB Help有提到這個動作比較危險,還是我記錯了? 第二個碼應該沒有法子釋放test裡面所存放的資料,反而是釋放了test本身。執行上會有不可預期的錯誤發生。
andychang1690
資深會員


發表:20
回覆:694
積分:442
註冊:2003-03-14

發送簡訊給我
#7 引用回覆 回覆 發表時間:2004-09-29 17:42:32 IP:221.169.xxx.xxx 未訂閱
引言:
引言: 1.test[i]->Name="test" IntToStr(i); 2.delete [] test; // 是釋放全部 發表人 - andychang1690 於 2004/09/29 11:07:50
關於andychang1690版友的回應,我有些想討論的地方: 第一個碼是在執行期改變了元件的名稱,我記得好像BCB Help有提到這個動作比較危險,還是我記錯了? 第二個碼應該沒有法子釋放test裡面所存放的資料,反而是釋放了test本身。執行上會有不可預期的錯誤發生。
感謝pwipwi版大指正: 1.test[i]->Name="test" IntToStr(i); 第一個碼是在執行期改變了元件的名稱,我記得好像BCB Help有提到這個動作比較危險,還是我記錯了? 這方式好像不太會產生問題!? 我個人是從不使用這方式,我只是直接引用benson5033的程式。 我個人一向都是 TButton *test; test = new TButton(this); test->Name ="test" IntToStr(i); Component_List->Add(test); 我一向使用TList來管理我動態產生的元件。 //Component_List = new TList; // h檔Public宣告 TList *Component_List; 2.delete [] test; // 是釋放全部 第二個碼應該沒有法子釋放test裡面所存放的資料,反而是釋放了test本身。執行上會有不可預期的錯誤發生。 我釋放的動作是於Form的OnCloseQuery事件中,我也只是提出供參考(因為我標記起來)! 我想或許這方面於程式運作中大家可以提出正確的方式! 我也是在學習中。 請指正!參考! Andy Chang
------
Andy Chang
ENIX007
高階會員


發表:28
回覆:274
積分:185
註冊:2003-11-27

發送簡訊給我
#8 引用回覆 回覆 發表時間:2004-09-29 18:48:24 IP:220.228.xxx.xxx 未訂閱
引言: benson5033:參考一下; .h檔 private: // User declarations 或 public: // User declarations TButton *test[10]; .cpp檔 void __fastcall TForm1::FormCreate(TObject *Sender) { for (int i=0; i < 10; i ) { test[i] = new TButton(this); test[i]->Name="test" IntToStr(i); } } // Form的OnCloseQuery事件 void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) { // 清除元件暫存檔 for (int i = 0; i < 10; i ) { delete test[i]; test[i] = NULL; } //或使用 // delete [] test; // 是釋放全部 } 請參考! Andy Chang
關於這部分的delete小弟提出一點個人意見,由於此處宣告的 test[10]是以固定大小的陣列方式宣告,當物件產生時,就已經 配置記憶體了,所以應該不用 delete [] test; 只需做delete test[i];的部分就行了... 除非宣告成 TButton **test; 那就必須在 delete test[i]; 之後再加上 delete [] test; 當然初始時也必須自行配置記憶體 test = new TButton*[10]; 有錯請指正 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
pwipwi
版主


發表:68
回覆:629
積分:349
註冊:2004-04-08

發送簡訊給我
#9 引用回覆 回覆 發表時間:2004-09-29 20:58:08 IP:211.76.xxx.xxx 未訂閱
關於上一篇我提到執行期改變Control的Name的討論, 後來我找了一下BCB的Help,有以下的說明:    Specifies the name of the control as referenced in code.     __property AnsiString Name = {read=FName, write=SetName, stored=false};    Description    Use the Name property to assign a new name to the control or to find out what the name of the control is.    By default, the IDE assigns sequential names based on the type of the control, such as 'Button1', 'Button2', and so on. Change these to more meaningful names that make the application? code more readable. The Name must be a valid Object Pascal identifier.     Warning: Do not change the Name property except at design time. Run time errors may result. 不過Andy版友也提到可以正常的作用, 不知道這個部份有沒有其他人有相關的經驗或見解?
andychang1690
資深會員


發表:20
回覆:694
積分:442
註冊:2003-03-14

發送簡訊給我
#10 引用回覆 回覆 發表時間:2004-09-29 21:47:56 IP:221.169.xxx.xxx 未訂閱
引言: 關於上一篇我提到執行期改變Control的Name的討論, 後來我找了一下BCB的Help,有以下的說明: Specifies the name of the control as referenced in code. __property AnsiString Name = {read=FName, write=SetName, stored=false}; Description Use the Name property to assign a new name to the control or to find out what the name of the control is. By default, the IDE assigns sequential names based on the type of the control, such as 'Button1', 'Button2', and so on. Change these to more meaningful names that make the application? code more readable. The Name must be a valid Object Pascal identifier. Warning: Do not change the Name property except at design time. Run time errors may result. 不過Andy版友也提到可以正常的作用, 不知道這個部份有沒有其他人有相關的經驗或見解?
Unit1.h檔
private:        // User declarations
  TButton *test[10];
Unit1.cpp檔
void __fastcall TForm1::FormCreate(TObject *Sender)
{
  for (int i=0; i < 10; i  ) {
    test[i] = new TButton(this);
    test[i]->Parent=Form1;         // 指定 Parent 才會顯示
    test[i]->Name="test" IntToStr(i);
    test[i]->Top=(i 1)*30;
    test[i]->Left=50;
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose)
{
  delete [] test; 
}
BCB6,Win-XP。
請參考!
Andy Chang
------
Andy Chang
andychang1690
資深會員


發表:20
回覆:694
積分:442
註冊:2003-03-14

發送簡訊給我
#11 引用回覆 回覆 發表時間:2004-09-29 22:30:38 IP:221.169.xxx.xxx 未訂閱
轉貼一篇文章:
http://members.lycos.co.uk/happybcb/article/tips/cbc_20.htm
BCB經驗點滴->內存問題
一、"delete p" 會刪去 "p" 指標,還是它指到的資料,"*p" ?
  該指標指到的資料。"delete" 真正的意思是:「刪去指標指到的東西」(delete the thing pointed to by)。
    同樣的英文誤用也發生在 C 語言的「釋放」指標所指向的記憶體("free(p)"真正的意思是:"free_the_stuff_pointed_to_by(p)" )。 
二、能 "free()" 掉由 "new" 配置到的、"delete" 掉由 "malloc()" 配置到的記憶體嗎?  不行。在同一個程式裏,
    使用 malloc/free 及 new/delete 是完全合法、合理、安全的;但 free 掉由 new 配置到的,或 delete 掉由 malloc 
    配置到的指標則是不合法、不合理的。 
三、為什麼該用 "new" 而不是 malloc() ?
  建構子/解構子、型別安全性、可被覆蓋(overridability)。建構子/解構子:和 "malloc(sizeof(Fred))" 不同,
    "new Fred()" 還會去呼叫Fred 的建構子。同理,"delete p" 會去呼叫 "*p" 的解構子。 
    型別安全性:malloc() 會傳回一個不具型別安全的 "void*",而 "new Fred()" 則會傳回正確型態的指標(一個 "Fred*")。 
    可被覆蓋:"new" 是個可被物件類別覆蓋的運算子,而 "malloc" 不是以「各個類別」作?覆蓋的基準。 
四、為什麼 C   不替 "new" 及 "delete" 搭配個 "realloc()" ? 
  避免你?生意外。當 realloc() 要拷貝配置區時,它做的是「逐位元元 bitwise」的拷貝,這會弄壞大部份的 C   物件。
    不過 C   的物件應該可以自我拷貝才對:用它們自己的拷貝建構子或設定運算子。 
五、該怎樣配置/釋放陣列?
  用 new[] 和 delete[] : 
    Fred* p = new Fred[100]; 
    //... 
    delete [] p; 
    每當你在 "new" 運算式中用了 "[...]" 的話,你就 *!*必須*!* 在 "delete" 陳述中使用 "[]" 。這語法是必要的,
    因為「指向單一元素的指標」與「指向一個陣列的指標」在語法上並無法區分開來。 
六、萬一我忘了將 "[]" 用在 "delete" 由 "new Fred[n]" 配置到的陣列,會發生什麼事?  
    災難。這是程式者的--而不是編譯器的--責任,去確保 new[] 與 delete[] 的正確配對。若你弄錯了,
    編譯器不會產生任何編譯期或執行期的錯誤訊息。堆積(heap)被破壞是最可能的結局,或是更糟的,你的程式會當掉。 
七、成員函數做 "delete this" 的動作是合法的(並且是好的)嗎?
   只要你小心的話就沒事。所謂的「小心」是: 
    1) 你得 100% 確定 "this" 是由 "new" 配置來的(而非 "new[]",亦非自訂的 "new" 版本,一定要是最原始的 "new")。 
    2) 你得 100% 確定該成員函數是此物件最後一個會去呼叫的。 
    3) 做完自殺的動作 ("delete this;") 後,你不能再去碰 "this" 的物件了,包括資料及運作行為在內。 
    4) 做完自殺的動作 ("delete this;") 後,你不能再去碰 "this" 指標了。換句話說,你不能查看它、
       將它與其他指標或是 NULL 相比較、印出其值、對它轉型、對它做任何事情。 
    很自然的,這項警告也適用於:當 "this" 是個指向基底類別的指標,而解構子不是virtual 的場合。 
八、該怎麼用 new 來配置多維陣列? 
  有很多方法,端視你對陣列大小的伸縮性之要求而定。極端一點的情形,如果你在編譯期就知道所有陣列的維度,
    你可以靜態地配置(就像 C 一樣):
    class Fred { /*...*/ }; 
    void manipulateArray() 
    { 
      Fred matrix[10][20]; 
      //使用 matrix[i][j]... 
      //不須特地去釋放該陣列 
    } 
    另一個極端情況,如果你希望該矩陣的每個小塊都能不一樣大,你可以在自由記憶體裏配置之:
    void manipulateArray(unsigned nrows, unsigned ncols[]) 
    //'nrows' 是該陣列之列數。 
    //所以合法的列數為 (0, nrows-1) 開區間。 
    //'ncols[r]' 則是 'r' 列的行數 ('r' 值域? [0..nrows-1])。 
    { 
      Fred** matrix = new Fred*[nrows]; 
      for (unsigned r = 0; r < nrows;   r) 
      matrix[r] = new Fred[ ncols[r] ]; 
      //使用 matrix[i][j]... 
      //釋放就是配置的反動作: 
      for (r = nrows; r > 0; --r) 
        delete [] matrix[r-1]; 
      delete [] matrix; 
    } 
請參考!
Andy Chang
------
Andy Chang
richtop
資深會員


發表:122
回覆:646
積分:468
註冊:2003-06-10

發送簡訊給我
#12 引用回覆 回覆 發表時間:2004-09-29 22:55:26 IP:211.76.xxx.xxx 未訂閱
大家好:    覺得之前自己回答這個問題時,出現了若干盲點,考慮不夠周詳。看了大家的意見後,也做些測試,在此把心得說出來與大家分享及討論。 我首先做了一個測試,先加上 > < class="code"> void __fastcall TForm1::Button1Click(TObject *Sender) { //* case 1: delete [] test; //*/ /* case 2: for (int k=0; k<10; k ) { delete test[k]; test[k] = NULL; } */ } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { for (int i=0; i < 10; i ) { test[i] = new TButton(this); test[i]->Parent=Form1; // 指定 Parent 才會顯示 test[i]->Name="test" IntToStr(i); test[i]->Top=(i 1)*30; test[i]->Left=50; } } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCloseQuery(TObject *Sender, bool &CanClose) { delete [] test; } //--------------------------------------------------------------------------- TButton *test[10]; // test:表示一個陣列,共有10個元素且型態為(TButton *) // 系統最後會釋放這塊記憶體。 TButton **test; // test:指標變數,能指向一個型態為(TButton *)的陣列 test = new TButton*[10]; // 指向含有十個型態為(TButton *)變數的記憶體區塊的起始位址 ..... delete [] test; // 必須自行釋放這塊記憶體! 不管上述哪種方式,當我們動態產生元件時,也就是: for (int i=0; i < 10; i ) { test[i] = new TButton(this); ..... } 都需要自行釋放它們。 至於test呢?就要看我們在程式中是如何宣告它的。 RichTop 敬上 =====***** 把數學當工具,可以解決問題;將數學變能力,能夠發現並解決問題! =====#####
benson5033
一般會員


發表:44
回覆:47
積分:18
註冊:2004-08-16

發送簡訊給我
#13 引用回覆 回覆 發表時間:2004-10-02 23:19:13 IP:61.230.xxx.xxx 未訂閱
謝謝各位的幫忙,我的問題已經解決了,其實不是你們的方法不行,是我少了一個步驟,感謝各位
系統時間:2024-05-03 1:56:06
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!