續上集…
-
STL container 的 clear 真的就 clear 乾淨了嗎?
相信很多人在寫 C++ 時,都會想利用 STL 來省去一些造輪子的麻煩,其中最常被使用的就是像
std::vector
或std::list
這類的 container,常常有人就拿它們來當 variable-length 的 array 來解決問題。然後可能就會有像這樣子的 code 出現:
[code lang=”cpp”]
…
std::vectorvec;
…
MyClass* pObj = new MyClass(…);
vec.push_back(pObj);
…
…
// 用完 vec 之後,試圖把它清除掉
vec.clear();
[/code]
很多人以為這樣寫,clear()
method 就會幫你把曾經放進去的 element 給清乾淨了,可惜並不是這麼美好!沒錯,clear()
的確是會把vec
裡的 elements 都清掉沒錯,但你有沒有注意到,vec
的 element type 是MyClass*
,是個指標的資料型態,也就是說:呼叫clear()
method 清掉了這些個指標,但卻沒有清掉指標所指到的 object!所以最起碼你應該這麼寫:
[code lang=”cpp”]
// 以 iterator 走訪整個 vec 裡的元素,
// 然後一一 delete 掉指到的 object
for (std::vector::iterator iter = vec.begin(); iter != vec.end(); ++iter)
{
delete *iter;
}
vec.clear();
[/code]
如果你有大量使用 STL 習慣的人,一定要小心 container 裡的 element 是不是真的都清乾淨了。 -
如果你很懶,請愛用
std::auto_ptr
之前有提到 new 過就不要忘記 delete 它,但如果你常常忘記 delete 的話,不妨用
std::auto_ptr
來幫你吧!std::auto_ptr
是一個 smart pointer ,它雖然是一個 templated class,但它的 object 用起來就好像一般的指標一樣,差別在於:當這個 object 被 destroy 時,它會檢查指到的記憶體是不是經由 new 所配置來的,如果是,就順便清掉!下面就用簡單的例子來說明:
[code lang=”cpp”]
#include// 要引入 memory 標頭檔
…
{
std::auto_ptrpObj(new MyClass());
…
// 這時就可以使用 pObj->xxx() 來呼叫 method,
// 就好像你用 MyClass *pObj; 宣告一樣。
…
// 此時 pObj 被 destroy 了,
//而它指到的記憶體也會被釋放。
}
…
[/code]
看起來方便多了,是吧?不過沒用過std::auto_ptr
的人要注意到,它是沒辦法經由 copy assignment 來與另一個std::auto_ptr
object 來 share 指到的記憶體位置。比方說下列的 code 就會使p1
最後指到null
:
[code lang=”cpp”]
…
std::auto_ptrp1(new MyClass());
std::auto_ptrp2;
p2 = p1;
…
[/code]
這樣p2
會指到原本p1
指到的記憶體,但卻讓p1
指到 null 了。如果你想要使用可以 share 的 smart pointer,或許你可以參考 boost library 裡的 shared_pointer,或是等待 C++ 2.0 的標準函式庫(詳情可見 TR1 draft)
簡單地寫了最近常碰到的問題,歡迎各方高手不吝賜教。:)
不好意思,我記得autoptr會無差別delete他所存的指標耶@@
#include
#include
class Dummy
{
public:
Dummy()
{
std::cout << “A dummy created” << std::endl;
}
~Dummy()
{
std::cout << “Dummy deleted” << std::endl;
}
};
void dummyFun(Dummy* ptrDummy)
{
std::cout << “Function started” << std::endl;
std::auto_ptr aPtr(ptrDummy);
std::cout << “Funtion ended” << std::endl;
}
int main()
{
std::cout << “Program started” << std::endl;
Dummy iAmDummy;
dummyFun(&iAmDummy);
std::cout << “Program ended” << std::endl;
return 0;
}
在VC2008 express中如果在debug build中在auto_ptr嘗試delete從main傳過去的資料VC2008會自動break報告問題出現,而在release build中在dummyFun會被delete一次而離開main再destruct一次。
是因為這是VC2008用的政策嗎?
這…VC對 STL 的實作我一直都覺得很神妙,也許我沒辦法回答您 🙁
抱歉,我不應該在這邊貼code的orz
http://rafb.net/p/vnAGy329.html
因為 debug build 會給比較嚴謹的 memory routine.
你嘗試因為 auto_ptr 去 delete heap-based 的指標,會給錯誤
而 release build 就沒有那麼嚴謹,通常簡單的程式會繼續跑下去 直到發生到不可回復的錯誤為止。
天啊!二年以前的問題竟然有人回答!謝謝你!