2017-07-27 187 views
0

我做了一個名爲cell的類。這個類裏面有一個cell指針數組。標題是這樣的:在C++中刪除指針數組時,析構函數崩潰了

class cell 
{  
public: 
    cell(); 
    cell *c[8]; 
    void creatcells(); 
    virtual ~cell(); 
    .. 

} 

cpp文件看起來像這樣:

cell::cell() 
{ 
//ctor 
for(int i=0;i<8;i++) 
{ 
    c[i]=NULL; 
} 

} 


void cell::creatcells() 

{ 
    cell c1,c2,c3,c4,c5,c6,c7,c8; 

    c[0]=&c1; 
    c[1]=&c2; 
    c[2]=&c3; 
    c[3]=&c4; 
    c[4]=&c5; 
    c[5]=&c6; 
    c[6]=&c7; 
    c[7]=&c8; 
} 

cell::~cell() 
{ 
    for(int i=0; i<8; i++) 
    { 
     if (c[i]!=NULL) 
     { 
        delete c[i]; 
     } 
    } 
    delete[] c; 

} 

但每次節目結束時,它崩潰,爲什麼呢?
我試過沒有if (c[i]!=NULL),但這沒有幫助。只有沒有for循環代碼完美結束,但我知道這也必須刪除。 我想我正確地寫了析構函數,不是嗎?

+0

使用調試器打開程序,它將在崩潰點 – user5821508

+3

'單元格c1,c2,c3,c4,c5,c6,c7,c8;中斷;'< - 所有這些超出了方法結尾的範圍,該地址無效。 – crashmstr

+2

變量'c1','c2'等都不存在於函數'createcells'的範圍之外。所以存儲指向它們的指針會讓你有一個充滿懸掛指針的數組。 – CoryKramer

回答

5
void cell::creatcells() 
{ 
    cell c1,c2,c3,c4,c5,c6,c7,c8; 

    c[0]=&c1; 
    c[1]=&c2; 
    ... 

上述所有cell對象在createcells()。所以delete c[i];在析構函數結束時自動銷燬是UB.What你想要的是

c[0]= new cell(); 
c[1]= new cell(); 
+3

你真的*想要的是一個'std :: vector '和返回值優化! – Bathsheba

+0

通過這樣做,我是否必須像以前那樣刪除它們?還是被毀壞?我按照你的建議更改了代碼並保留了我的析構函數,但它再次崩潰了...... –

+0

@NoamChai'delete [] c;'你不需要這個,因爲你已經刪除了循環中的所有對象。 –

4

您試圖取消引用指向和delete變量的變量,這些變量具有自動存儲期限並且不再處於範圍內!你的編譯器沒有提醒你這些嗎?

您的程序的行爲因此是undefined

你只曾經對的delete[]new[],用new一個delete;儘管您可以將delete(甚至是new )委託給像std::unique_ptr這樣的託管指針類。

爲什麼不重構爲std::vector<cell>並利用返回值優化


使用std::make_unique

+0

...並且將'new'委託給'std :: make_unique' –

+0

@MartinBonner:謝謝你,指出了這一點。 – Bathsheba

3

cell::createcells函數的變量是當地和超出範圍並在函數返回時被破壞。當您嘗試刪除它們時,這些對象將不存在。取消引用這些指針將導致undefined behavior

何況你應該只有deletenew是什麼。而且因爲你沒有new所做的任何事情delete上的指針再次導致undefined behavior

的簡單解決方案是使用一個vector對象

std::vector<cell> c; 

然後,只需增加8個cell對象的矢量:

void cell::creatcells() 
{ 
    c = std::vector<cell>(8); 
} 

現在載體將含有8默認構造cell對象。不需要在構造函數或析構函數中做任何事情。事實上,我建議您根據the rule of zero完全刪除構造函數和析構函數。