2017-07-27 186 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完全删除构造函数和析构函数。