2014-01-30 47 views
0

我创建了一个子级,B,为此,我会打电话给A.创建一个'新'实例解决了析构函数崩溃?

我写了这个工作代码的类,所以我要推广的实际代码:

class A 
{ 
public: 
    A() 
    { 
    important_variable = new Type(); 
    ... 
    }; 

    ~A (void) { delete(important_variable); };  // Default destructor 
    // more methods 

protected: 
    Type  *important_variable; 
}; 

class B : public A 
{ 
public: 
B() : A() { important_variable = another_var; } 
~B() {}; 

Type *another_var; 
}; 

有了这个B代码导致我的程序崩溃了'未处理的异常'。

现在,当我为B类代码改成这样:

class B : public A 
{ 
public: 
B() : A() { another_var = new Type(); important_variable = another_var; } 
~B() {}; 

Type *another_var; 
}; 

异常消失。

我认为我原来的B代码导致我的程序崩溃,因为A试图删除一个仍然被另一个变量指向的变量。这个推理是否正确?为什么B的新代码会导致我的程序正常工作?

+0

你的推理可能是正确的(不能说没有看到更多的代码)。第二个代码的作用是因为您为每个实例创建了一个新对象,所以每次删除一个对象时,它都不会踩到其他对象的脚趾。但是你的代码有内存泄漏。你不能只重新分配一个指针而不做一些关于它指向的对象的东西。 – Dave

回答

2

有在你的代码中的许多缺陷,但一个最有可能导致应用程序崩溃是这一行:

important_variable = another_var; 

another_var不指向任何地方,可以将其删除。但是important_variable被指向相同的地方,然后在A的构造函数中被删除。

您的“解决方案”以内存泄漏为代价掩盖了问题。当你这样做

another_var = new Type(); important_variable = another_var; 

原来的动态分配Type对象important_variable指出丢失。

除此之外,您需要遵循rule of three

+0

第一个代码也有内存泄漏。 – Dave

+0

如何摆脱内存泄漏,仍然保持现有的功能? – Undefined

+0

@Dave是的,它的确如此。 – juanchopanza

0

新增和删除仅用于处理堆分配。我怀疑在B类的第一个列表中,another_var很可能分配在堆栈上,这是析构函数中导致异常的原因。此外,每当你有一个基类,你真的应该使其破坏者virtual

0

原始版本崩溃,因为您将important_variable设置为未初始化的another_var,然后尝试删除此未初始化的值。 在“已更正”的版本中,您至少不会删除未初始化的变量,但仍然包含内存泄漏 - 您将新分配的内存分配给important_variable,然后立即将该值分配给该变量another_var,因此最初分配的内存不是更长的访问时间并会泄漏。

相关问题