2011-03-28 22 views
1

解放出來一個指針:從給定的代碼中的另一個功能

#include<iostream> 
using namespace std; 

class String 
{ 
     char *pstr; 
     unsigned size; 
     public: 
      String(){ pstr=0;size=0;} 
      String(const char *); 
      void show(){ cout << pstr << endl ; } 
      ~String() { cout << "In Dtor" << endl; delete [] pstr; } 

}; 

String::String(const char * cptr) 
{ 
    size = strlen (cptr) + 1; 
    cout << "String is - " << cptr << " - of size " << size - 1 << endl ; 
    pstr = new char [ size ] ; 
    for (int i = 0 ; i < size ; i++) 
     pstr[ i ] = cptr [ i ]; 

} 



int main() 
{ 
    String s("Hello World"); 
    s.show(); 
    s.~String(); 
} 

輸出:

String is - Hello World - of size 11 
    Hello World 
    In Dtor 
----Debug Assertion Failure---- 
    In Dtor 

爲什麼析構函數再次調用?當我調用析構函數時?

什麼是斷言失敗?

也是代碼有效嗎?

char * ptr=0;  

void fun() 
{ 
     const char * p = "Hello World"; 
     int size = strlen(p)+ 1; 
     cout << size << endl; 
     ptr = (char *)malloc(size); 
     for (int i = 0 ; i < size ; i++) 
     ptr[ i ] = p [ i ]; 
     cout << p << endl << ptr << endl ; 
} 

int main() 
{ 
    fun(); 
    free (ptr); --> Note 
} 

指針可以從另一個函數中釋放嗎?這是我在這裏試圖理解的主要內容。

+0

不要求顯式調用析構函數,您不使用免費商店。 – DumbCoder 2011-03-28 11:53:10

+0

@DumbCoder:即使在使用堆時,也不要明確調用析構函數。你只能調用'delete'。 – Xeo 2011-03-28 11:58:10

+0

@Acme:在你的編輯:是的,你可以,但那不屬於同一個問題。另外,我確信它之前已經回答了:在提問之前進行搜索! – Xeo 2011-03-28 12:01:11

回答

10

你不應該手動調用析構函數 - 當s在最後的「}」

聲明失敗意味着一種叫assert(somecondition)和somecondition是假超出範圍時它的調用。這是一種用來驗證你的假設的技術 - 如果你的代碼依賴於某些特定的條件,那麼除非你有錯誤,否則你插入一個斷言。

然後,您可以選擇啓用斷言進行編譯 - 這意味着如果您的假設錯誤,您會得到這樣的錯誤。對於發佈版本,通常會禁用斷言 - 不會爲assert語句生成代碼,也不會產生額外的運行時成本。

有些情況下,手動調用析構函數是正確的 - 在您瞭解和使用「放置新的」之前,您不需要這些。

+1

+1 - 澄清:析構函數被手動調用一次,然後當's'超出範圍時再次調用析構函數。 – 2011-03-28 11:56:59

1

除了什麼埃裏克已經表示:

刪除手動析構函數調用後您的代碼將仍然容易出現雙重缺失:你必須要麼禁止拷貝構造函數/賦值運算符,或者正確地實現它們(你如果你堅持擁有堆分配的內存,就需要引用計數)。

+1

這應該是一個評論,不是? :) – Xeo 2011-03-28 12:02:26