2010-11-02 58 views
0

我有一個C++代碼,其中有多種數據類型。重要的是,我有一個類:我應該只需要擔心新的並將其與刪除匹配?

class coordinate{ 
    int x, y; 
    public: 
    void set_values(int, int); 
} 

然後我可能會說:

coordinate* origin = new coordinate; 

顯然,收回分配給原產地記憶我終於說:

delete(origin); 

到目前爲止,好...

我的問題是有沒有其他數據類型的刪除/銷燬我必須絕對手動注意防止內存泄漏?

在考慮中的其它數據類型是:

串(此數據類型的一個目的似乎有一個端()函數),字符串流,CHAR []。

例如,我有一個函數的setName(),它會從main()中反覆做這個叫:

void setname(){ 

    for(int k = 0; k < 10; k++){ 
     string NAME = "Point "; 
     stringstream s; 
     s << k; 
     NAME += s.str(); 
     char name[7]; 
     strcpy(name,NAME.c_str()); 
     /* some other stuff... */ 
     NAME.end(); //<--------------is stuff like this really needed? 
//will memory held by NAME, s and name be automatically released as k increments? 
    } 
} 
+0

'std :: string :: end()'是STL迭代機制的一部分。它與內存管理無關。 :) – 2010-11-02 22:15:30

+2

您是否想過查找'std :: string :: end()'是做什麼的? – 2010-11-02 22:15:43

+0

@Oli:我還是他? ; p – 2010-11-02 22:19:59

回答

1

答案是:這取決於。如果您的代碼使用new分配任何東西(stringcoordinate類的實例,stringstream等),則某些代碼(也許是您的)應該使用delete它。否則,如果您在堆棧上創建一個字符串並將其傳遞給複製構造函數,則不必刪除它。

而且:根本不需要NAME.end()。函數end()實際上返回一個迭代器,指向字符串的末尾;它不做任何清理。所以在你的代碼中,不需要撥打end()

+0

因此...缺乏新的配置我可以盲目擔心內存泄漏? – Tryer 2010-11-02 22:19:27

+0

如果你沒有分配內存,_usually_你也不需要釋放它。但是,有一些特殊情況:有些函數正在爲您分配數據,希望您能夠釋放它們。但這種做法非常罕見,必須在適當的文件中適當描述。 – Vlad 2010-11-02 22:22:22

+0

@Tryer:理想的是,是的。除非你使用的底層事物的程序員已經搞砸了,這經常發生。但只要你匹配每一個新的刪除,不要使用任何隱藏的內存函數(malloc ...)或C字符串函數,你應該沒問題。 – Lagerbaer 2010-11-02 22:22:39

4

new應該匹配delete,每new []delete [],每mallocfree(但在C沒有使用這些++ ......)

2

作爲一般規則:如果你new它,delete它。如果你new[]吧,delete[]吧。如果你malloc()它,free()它。

否則,你一般不必做任何事情。 (如GlobalAlloc()在Windows或CFStringCreate()在Mac OS X系統特定的東西/ iOS設備都有自己的規則。請參閱您的手動/ FAQ/MSDN上這些特定系統API的信息。)

+0

請注意,Win32 API似乎根本沒有任何規則,除了「檢查每個函數的文檔......並徹底閱讀它們之外,還有一些需要你分配一個系統然後釋放的緩衝區,有時它是反過來,API爲你提供了一個系統分配的緩衝區,你必須重新分配,有時候你必須同時執行這兩個操作,有時候也不行,而且你應該用來分配或釋放的函數也不盡相同。 – jalf 2010-11-03 00:09:48

+0

爲什麼上帝發明了抽象圖書館。/我不寒而慄 – 2010-11-03 01:29:52

0

您可以隨時調查boost::shared_ptr 。你仍然必須做'新',但刪除是由共享ptr內部處理的。

0

使用C++ 0x/TR1 shared_ptr <>如果可以的話,它們絕對是驚人的,有人說性能會影響,但仍然只有在探查器投訴shared_ptr時才考慮其他選擇。共享指針是線程安全的,並且在重新分配時具有非常好的行爲(shared_ptr <> :: reset將拆分引用)。

你應該注意的唯一的事情是new vs new [],這就是爲什麼我喜歡c類型的內存分配器(calloc,malloc,free),如果我不需要構造函數和析構函數(即POD類型)。

對於C型分配器可以使用:shared_ptr<char> charptr((char*)calloc(10, sizof(char)), free);

PS:對於其他對象,注意內核句柄和GDI對象(至少在Windows上),它們不完全泄漏內存在一個傳統意義上的,但必須關閉。

此外,c類型函數經常返回malloc'd指針。

0

不,不,不。您使用RAII - 這是異常安全的。

基本上,當一個自定義類型的對象超出C++範圍時,它會調用一個特殊函數(稱爲析構函數)。這用於清理所有資源。它實際上是自動應用的,實際上,在所有可以合理繼續執行程序的情況下都會調用它,而有些則不能。

這意味着你永遠不必釋放自定義類型創建的內存 - 它應該釋放自己。你不必釋放由std :: string分配的內存,也不需要std :: stringstream。 std :: string :: end()即將結束迭代。通常,對於需要自定義釋放的任何資源,您將以自定義類型包裝它們,以便它們不再需要手動釋放。

對於使用new分配的自定義類型,可以使用auto_ptr,它在超出作用域並釋放內存時立即銷燬該對象,或者可以使用shared_ptr,該對象在所有指向它通過一些魔法。還有其他類型的智能指針,對於任何給定資源,您可以編寫自己的自定義管理類型。這極大地提高了您的程序的安全性,從而避免了性能損失。另外,你永遠也不應該使用char *或任何相關類型(char []等)來存儲C++中的字符串。使用std :: string。您當前的代碼是不可維護的,因爲它會死掉,或者如果您需要超過7個字符,可能會導致隨機錯誤。 C風格的字符串函數(strcpy)同樣極端地被棄用,不應該被使用。 (當然,每個規則都有例外,但是C風格的字符串,你必須非常先進才能正確利用它們的優點)。

一般的規則是,如果你曾經調用一個函數來釋放一個析構函數以外的資源,那麼你幾乎肯定會寫錯你的程序。

相關問題