[C++] delete 一個字串 |
尚未結案
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
blk5743
高階會員 發表:34 回覆:371 積分:236 註冊:2003-11-17 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
char *GetString() { char *str; str = new char[100]; strcpy(str, "abc"); return str; } main { char *S; S = GetString(); // do something delete [] S; return 0; }1.這樣,只要你是用括號所NEW出來的東東。 你就用 DELETE 括號的方式去還。 2.前一個回答有些問題。 引言: 你宣告char *S,所以你要delete的不是S 而是你GetString()中new出來的字串這裏有些錯。 基本上我的寫法假設我的 str 指標內容存著 300 的話。 那我在 GetString 這個函數結束時,我的 str 就會消失掉了。 因為函數的生命週期的問題。 所以用RETURN的方式把 300 交到上層的函數 這時候就會變成 S 存的值是 300。 所以 delete [] S;是正確的。 而不是 delete [] str; |
blk5743
高階會員 發表:34 回覆:371 積分:236 註冊:2003-11-17 發送簡訊給我 |
引言: 引言: -------------------------------------------------------------------------------- 你宣告char *S,所以你要delete的不是S 而是你GetString()中new出來的字串 -------------------------------------------------------------------------------- 這裏有些錯。 基本上我的寫法假設我的 str 指標內容存著 300 的話。 那我在 GetString 這個函數結束時,我的 str 就會消失掉了。 因為函數的生命週期的問題。 所以用RETURN的方式把 300 交到上層的函數 這時候就會變成 S 存的值是 300。 所以 delete [] S; 是正確的。 而不是 delete [] str;暗黑破壞神 你好 其實我想說的是jackyung在GetString() new一個空間, 就應該在GetString()裡面delete掉,而不是如大大你舉例的 在main()中delete [] str; 或許是我誤會jackyung的意思,再加上我表達的不好 引起jackyung的疑惑,在此說聲不好意思 另外也感謝暗黑破壞神解釋整個流程 讓大家都能夠得到收穫 |
folkchen
高階會員 發表:9 回覆:232 積分:173 註冊:2003-10-09 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
上一篇回覆又得到兩個問題。
再回一次
引言: 其實我想說的是jackyung在GetString() new一個空間, 就應該在GetString()裡面delete掉,而不是如大大你舉例的 在main()中delete [] str;這一句話就有問題了。妳的觀念得要修正一下囉。 ^_^ 我之所以會舉這樣的例子。就是因為我們用C會用到函數。 也會用到指標。記憶體這些東東。 而一個函數的生命週期只在我們呼叫它的時候,它會存在。 同樣的。在這個函數中所宣告的所有東西。的生命週期。也只活到這個函數的RETURN為止。(PS。有STATIC宣告例外)。 所以。你可以看到 blk 所說的。是一種很”良好”的記憶體使用習慣。 在那裏宣告的。就在那裏刪除。以免留下”禍根”。 但是。我們會再發現一件事。。。。那我怎麼把字串內容傳到上一層的函數呢? 那就是把要回傳的字串放在函數的參數回傳。 也就是會變成”傳址呼叫”法。或是”參照呼叫”法。前者是標準C的東東。 後者是C++多出來的東西。^_^ 這樣就可以由上一層拿到一塊記憶體。然後對這塊記憶體”胡搞瞎搞”之後。 就離開這個函數。當然。記憶體內容就會被這個函數修改。而達到這個函數的 功能。 而我所用的方法是比較”危險”的作法。也就是說。使用者必須記得那些東西是必須手動刪除。以我這個作法。是在子函數向系統要求要一塊記憶體。 記得。我跟系統要一塊記憶體。我就得”自行管理”這塊記憶體。 這塊記憶體並不會因為函數結束就被回收。 這個回收機制在C是直到你離開這個程式。它才會被系統回收。 所以。你用到這個方法時,你要記得要DEL它。^_^ 因此。我在 main 這層把它釋放掉。 OK?在這方面有問題,歡迎討論。 再來下一個問題 引言: 可是你的Function的宣告是指標耶 > char *GetString() 那你 return 回去的不就是一個指標位址嗎 可是因為生命週期的關係 這個位址的內容是不是會被釋放掉 那被傳回的值,還會是正確的嗎??嗯。不錯,你有函數生命週期的觀念。 我是要回傳一個字元指標回去沒錯。 就我剛才所說的。str 會被回收。因為函數的生命週期問題。 在RETURN時就會被收回。可是 str 所指到的那個空間。並不會被回收。 因為那是我跟系統要來的。它還是會留著。 我必須跟”其它人”講。我有要了這一塊空間。 請接手的人,務必幫我處理好這塊空間。 不然,這塊空間就會一直存在。 每執行一次這個函數。我都會多留一小塊的”垃圾”。 所以我把 STR 的值回傳了啊。 讓 MAIN 可以DEL它。 如果你想。它會在RETURN時就不見? 那你要看一下。把它變成組合語言的話。它會是一堆的 push, pop 的堆疊動作。之後才是 RET。所以,它在把資料傳回前。並不會”消失”。 |
folkchen
高階會員 發表:9 回覆:232 積分:173 註冊:2003-10-09 發送簡訊給我 |
>在RETURN時就會被收回。可是 str 所指到的那個空間。並不會被回收。
>因為那是我跟系統要來的。它還是會留著。 我的問題是,當離開這個Function後,那一塊記憶體,C是否認為它是Free的
在下一次有人向C要空間時,C"有可能"把它給配置出去了
若YES,就有可能會有問題
若NO,該空間的位置只要沒有Delete,都會一直留到整個程式結束才放掉,除了佔空間,就不會有其他問題 若為NO的話,是只要 New 出來的東東都有這樣的問題嗎?一定要做Delete才可以嗎?
那同一個Function被Call了100次,它會被配置出100個空間嗎?
還是會用同一個空間?
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
引言: >在RETURN時就會被收回。可是 str 所指到的那個空間。並不會被回收。 >因為那是我跟系統要來的。它還是會留著。 我的問題是,當離開這個Function後,那一塊記憶體,C是否認為它是Free的 在下一次有人向C要空間時,C"有可能"把它給配置出去了 若YES,就有可能會有問題 若NO,該空間的位置只要沒有Delete,都會一直留到整個程式結束才放掉,除了佔空間,就不會有其他問題NO. 必須經過 delete 它才會釋放 引言: 若為NO的話,是只要 New 出來的東東都有這樣的問題嗎?一定要做Delete才可以嗎?YES.不然就是要結束程式。作業系統才會去回收。 引言: 那同一個Function被Call了100次,它會被配置出100個空間嗎? 還是會用同一個空間?如果你沒釋放掉。那就會是不同的空間。 如果你有釋放掉。就”不一定”會是相同的空間。 嗯。妳似乎會覺得怪怪的。。。。那你去看一看 LINK LIST的用法吧。 把 malloc 改成NEW 就是了。^_^ |
folkchen
高階會員 發表:9 回覆:232 積分:173 註冊:2003-10-09 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
這個規定還真有點不好用,int *GetAint; 和 int *GetAintArray; 有同樣的回傳形式宣告,卻要有不同的刪除方式,若全都用 delete [] 來刪不知是不是會有不良影響 看看以下這個
claee A { char *data publuc: A(char *Src) { data = Src; } ~A(void) { // 這裡要怎麼處理 delete data; delete [] data; } };發表人 - jackyung 於 2005/02/28 18:42:35 |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
好吧,我就做個例子來討論,用 BCB6 編譯以下例子。 以下證明兩件事:
1. list 會 delete 不是它 new 的物件
2. list 是用 delete 不是用 delete []
#include |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
|
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
引言: 以下證明兩件事: 1. list 會 delete 不是它 new 的物件 2. list 是用 delete 不是用 delete []第一個明顯是錯的,以下是bcb的list中insert原始碼 iterator insert(iterator __position, const _Tp& __x) { _Node* __tmp = _M_create_node(__x); _List_node_base* __n = __position._M_node; _List_node_base* __p = __n->_M_prev; __tmp->_M_next = __n; __tmp->_M_prev = __p; __p->_M_next = __tmp; __n->_M_prev = __tmp; return __tmp; }在insert過程中,物件會被list用copy的方式create出來。 另外你在struct A中犯了一個錯誤:沒有考慮到copy constructor也要實作count加1。因此當物件是用copy construct建立時,count不會加1。所以雖然你的程式顯示最後count是0。但是new出來的A[2]已經是memory leakage了,是沒有放釋放的。你可以試試以下的程式碼並trace看看,就會發現錯誤在那兒了。 #include最後是有關delete和delete [],用在FDT和自定的class上作法是不同的,不能混為一談,一般比較深入的C語言的教科書都會提到。這部分內容很多,請自行參考了。 |
jackyung
一般會員 發表:22 回覆:46 積分:13 註冊:2004-01-24 發送簡訊給我 |
原來 list 是用複製的,嗯,效率和其他方面的考量...使用上要特別注意 至於字串不過是連續的記憶體空間,不用呼叫解構函數,用 delete 難道只會刪一個 byte 嗎?或者干脆都用 delete [] 去刪省得麻煩,以下不管怎麼刪
都能得到同一個位址
void __fastcall TForm1::Button1Click(TObject *Sender) { char string[25]; char *A1 = new char[10]; ultoa((unsigned)&(A1[0]),string,16); Edit1->Text = AnsiString(string); // delete A1; delete [] A1; char *A2 = new char[1]; ultoa((unsigned)&A2[0],string,16); Edit2->Text = AnsiString(string); // delete A2; delete [] A2; char *A3 = new char[2]; ultoa((unsigned)&A3[0],string,16); Edit3->Text = AnsiString(string); // delete A3; delete [] A3; }發表人 - jackyung 於 2005/03/02 01:09:14 |
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
會有delete和delete[]的不同要從compiler層去著眼,以本例來說你在執行期要釋放的是一個char*的資料型,但是compiler是無法在編釋時就知道char*到底是單純一個指標,還是一個array(而且array還有大小的不同)。
如果是一個array,釋放的區域大小是物件本身大小乘以個數,這些會記錄在heap相關的table裡。如果是用delete,釋放時根本不需要去找heap的資料表,直接釋放和資料大小相同的區域。如果語法上不區分delete和delete[],要如何知道要不要去讀heap的資訊?
這些資訊書本上是可以找到的,在Bjarne Stroustrup的The C Programming Language中有很明白的說明,請參考一下吧。
|
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
另外...你舉的例子我看了用久,不知道你要表達的是什麼。
會得到同一個位置也不奇怪,釋放後的空間再拿來用不是理所當然的?
而且我跑第一次時,前兩個位置還不同... 要是我把例子改成下面的碼,永遠位置就都不同...(好像沒什麼意義吧?)
void __fastcall TForm1::Button1Click(TObject *Sender) { char string[25]; char *A1 = new char[10]; ultoa((unsigned)&(A1[0]),string,16); Edit1->Text = AnsiString(string); char *A2 = new char[1]; ultoa((unsigned)&A2[0],string,16); Edit2->Text = AnsiString(string); char *A3 = new char[2]; ultoa((unsigned)&A3[0],string,16); Edit3->Text = AnsiString(string); // delete A2; delete [] A2; // delete A1; delete [] A1; // delete A3; delete [] A3; } |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
感謝版主pwipwi出來解說。
也讓我學到怎麼跟初學者討論問題的方法。
畢竟C++是我在民國78年左右開始學習使用的東西。
到現在已經有一大段的時間了。
有很多的觀念,已經像 1+1=2成為既定的事實了。
要我再去解釋為什麼。實在是有些困難。 至於 jackyung,我只能說。你必須再多看一些基本的書。
然後再進行進一步的學習。如果你的基礎沒打好。
就去學一些深入的課程,你會遇到很多的問題。
比方說。你會用到 std, 可是。你在寫程式時,會用到
巨集嗎?
基本上 Template 就是巨集的擴張使用。
如果你對巨集會對你的程式造成多大的問題,你就不該在還不了解的狀況
去使用它。 舉個書上的例子。
#define PI 3.145926; #define R 1; main() { printf("AREA=%d", 2*PI*R); return 0; }不知道上面這段程式,你看出問題了嗎? |
chtai
高階會員 發表:68 回覆:238 積分:116 註冊:2004-05-21 發送簡訊給我 |
|
pwipwi
版主 發表:68 回覆:629 積分:349 註冊:2004-04-08 發送簡訊給我 |
引言: 感謝版主pwipwi出來解說。 也讓我學到怎麼跟初學者討論問題的方法。 畢竟C 是我在民國78年左右開始學習使用的東西。暗黑前輩過獎了。 寫C真的有太多細節要注意,jackyung版友會有這些疑問 也是很正常的。我自已也有不少被指正的經驗... 而且大多是”某書的某頁已經回答了你的問題之類的”。 後來自已學乖了,只好老實的去看書。 C語言好書真的不少,正確又詳細... 如果以後有網友想多了解有關C語言的語言語意, 可以參考accu網站上的推薦書: http://www.accu.org/bookreviews/public/reviews/0sb/advanced_c__.htm 裡面Highly Recommended的書都是經典之作..。 我幾乎全都拜回來”收藏”... 相信對許多問題都可迎刃而解。 |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
|
chtai
高階會員 發表:68 回覆:238 積分:116 註冊:2004-05-21 發送簡訊給我 |
引言: 你沒發現你去compiler 它時。它會跟你說 error嗎? 可是那一行你怎麼看就是看不出錯在那邊? 這個就是用巨集的缺點。 加油。用力看一下。我相信你可以找出問題來。^_^Sorry 目前手邊一時沒有環境可以 compile,所以小弟沒有實際測過。 不過剛才小弟再看了一下,有兩點怪怪的。 就是,那兩行 #define 結尾似乎不該有分號吧? -- http://www.csie.nctu.edu.tw/~chtai/software.php 好用免費軟體的收集網頁,歡迎大家跟我分享或一同推廣免費軟體。 若您覺得這網頁不錯,也歡迎您將它傳出去 :)
------
My Web: http://nelson.csie.us My Blog: http://blog.nelson.csie.us |
暗黑破壞神
版主 發表:9 回覆:2301 積分:1627 註冊:2004-10-04 發送簡訊給我 |
呵。答對了。
而這是初學者常遇到的錯。
而且,在實作中。並不好除錯。
這也是我提出來在談 template 時。必須要小心的原因,
因為一個不小心。就會發生錯誤。
OO的出現。一方面說它會是軟體元件。是個黑盒子。
可是在某方面。它又不像硬體能有那麼良好的
文件說明。。。。。ETC。
所以。它在使用上,還是以充份了解之後才使用。 並不能像 jackyung 這樣隨便拿到個LIST就套用。
這也許在學校的報告是OK的。可是到了大一點的程式。
就會死得很難看了。 還是以打底,了解作業系統。了解編譯器。了解連結。它們分別做了什麼事。
才是寫程式的基本。
語言只是用來滿足前面幾個所設下的限制。
(當然,那些限制有些是來自硬體)。
這篇回太多了。再來交給版主大哥了。^_^
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |