2013-11-23 51 views
2

如果我在析構函數定義中註釋行arr = 0;,程序將終止並顯示錯誤。如果我取消註釋該行,即arr設置爲0,那麼程序執行時不會出現任何錯誤。爲什麼它是這樣的,因爲不需要將指針設置爲NULL。指針本身在析構函數執行後被銷燬。在析構函數中缺少ptr = NULL導致錯誤,在ptr設置爲NULL時正常工作。爲什麼?

Screenshot of the error

下面是我的代碼。

Array.h

#ifndef ARRAY_H 
#define ARRAY_H 
class Array 
{ 
    int* arr; 
    int size; 
public: 
    Array(int size = 10); 
    Array(const Array& arr); 
    ~Array(); 
    void display() const; 
}; 
#endif 

Array.cpp

#include "Array.h" 
#include <iostream> 
using namespace std; 

Array::Array(int size) 
{ 
    arr = new int[size]; 
    this->size = size; 
    for (int i = 0; i < size; i++) 
     arr[i] = i; 
} 

Array::Array(const Array& a) 
{ 
    arr = new int[a.size]; 
    for (int i = 0; i < a.size; i++) 
     arr[i] = a.arr[i]; 
    size = a.size; 
} 

Array::~Array() 
{ 
    delete[] arr; 
    arr = 0; 
} 

void Array::display() const 
{ 
    cout << endl; 
    for (int i = 0; i < size; i++) 
     cout << arr[i] << " "; 
    cout << endl; 
} 

Main.cpp的

#include <iostream> 
#include "Array.h" 
using namespace std; 

int main() 
{ 
    Array arr(4); 
    Array a1 = arr; 
    a1.display(); 
    arr.~Array(); 
    a1.display(); 

    return 0; 
} 

回答

4

你不應該在這裏調用析構函數:

arr.~Array(); 

arr超出範圍時,將再次調用析構函數。當在指針數據成員arr上調用delete[]時,會導致未定義的行爲。當您將其設置爲0時,您會側身解決問題,但事實仍然是,您不應該像這樣調用析構函數。

這裏是出了自動存儲對象的生命週期如何綁定到其範圍的例子:

#include <iostream> 

struct Foo 
{ 
    ~Foo() { std::cout << "Foo destructor\n"; 
}; 

int main() 
{ 
    std::cout << in main()\n"; 

    { 
    Foo f; 
    } // f gets destroyed here 

    std::cout << "Exiting main()\n"; 
}; 
+0

第二次調用析構函數嗎?如何在不存在的已經銷燬的對象上再次調用析構函數。 –

+0

@UmarShabbir對象存在,直到'main'退出。這是當析構函數被自動調用時。 – juanchopanza

+0

@UmarShabbir在C++中,編譯器確保堆棧中的每個對象都將在它定義的作用域的末尾自動銷燬。雖然可以自己銷燬對象,但您必須確保在同一位置創建一個新對象(在編譯器生成的代碼再次調用析構函數之前放置新的)。一般來說,你不會在容器類(std :: vector)之外找到顯式的析構函數調用或放置,除非你有一個非常好的理由,你應該避免自己調用它們。 – josefx

0

你並不需要顯式調用析構函數。 它們將在程序終止後執行。 http://www.learncpp.com/cpp-tutorial/86-destructors/ 看項目下的文章標題的構造方法和析構函數的時間

析構函數被寫入釋放分配給指針的內存。否則指針會被刪除,但其內存仍然懸空。 當程序終止時,所有的變量將從內存中丟失,所有的資源將被釋放,並且在那段時間內析構函數會執行它自己。

+0

在這種情況下,當'main'的作用域被留下時,調用析構函數,而不是在程序結束時。 – juanchopanza

+0

^正確的是 –

相關問題