在实际析构函数调用之前删除了字段变量?

时间:2012-01-10 15:57:17

标签: c++ destructor

在删除对象后进入析构函数之前,什么会使字段变量变得过时? 我正在寻找这个问题的答案我在这个网站上遇到过这个: Lifetime of object is over before destructor is called?

根本没有加起来:如果我在另一个SomeClass内声明了指向WrapperClass的指针,当我构造WrapperClass时,我需要创建一个{{1}在破坏包装器时它和new SomeClass。 这是有道理的,迄今为止已经奏效。 指针仍然有效并且正确地解析为析构函数,否则很明显我无法将其删除。

现在我的问题是当我调用析构函数时,delete的{​​00}}的字段成员(包括int和指向SomeClass数组的指针)都是垃圾。我刚刚在构造之后检查了包装器对象并且数据很好。包装器实际上是另一个WrapperClass类中的指针,当我破坏Main(它破坏包装器)但是如果我只是Main来自另一个方法的包装器时,就会出现问题delete。 我的偏执使我得到了上面提到的答案,现在我完全糊涂了。 有人想关注这里真正发生的事情吗?

编辑: MainNode

SomeClass

4 个答案:

答案 0 :(得分:2)

您需要使用标准库来实现此行为。

class Wrapper {
private:
    struct Node { /*....*/ };
    int numNodes;
    std::vector<std::unique_ptr<Node>> nodes;
public:
    Wrapper() : numNodes(0) { nodes.resize(SIZE); }
    // No explicit destructor required
    // Correct copy semantics also implemented automatically
};

class Main {
public:
    Main() : wrapper(new Wrapper()) {}
    // Again, no explicit destructor required 
    // Copying banned for move-only class, so compiler tells you
    // if you try to copy it when you can't.
private:
    std::unique_ptr<Wrapper> wrapper;
};

保证此代码正确执行。在C ++中,如果您使用了new[]deletedelete[],那么请立即重构您的代码以将其删除,并对使用非展示位置new进行三次审核 - 构建unique_ptr几乎是唯一有效的案例。这只不过是手动内存管理的常见预期结果。

答案 1 :(得分:2)

由于Grizzly没有回答,我会把它放在那里。

您的Main类和Wrapper类都需要正确实现的复制构造函数和赋值运算符。请参阅The Rule of 3

问题是,如果你的类被复制(这很容易发生而你甚至没有意识到),那么指针就会被复制。现在你有两个指向同一个地方的物体。当其中一个超出范围时,会调用析构函数,它会调用该指针上的delete,并且指向的对象会被销毁。然后另一个对象留下一个悬空指针。当它被破坏时,它会尝试再次在该指针上调用delete。

答案 2 :(得分:0)

包装器对象的生命周期已结束,但整数和指针子对象以及指针对象仍处于活动状态。当您在指针上调用delete时,指针的生命周期结束,但指针仍然保持活动状态。指针的生命周期在你的dtor完成后结束。

因此,如果您的成员已经损坏,还有其他事情正在发生。

答案 3 :(得分:0)

<击>

<击>
Node** nodes;

应该是

Node * nodes;

<击> 析构函数也是错误的。它应该是:

for(int i = 0; i < numNodes; i++)
    delete nodes[i];
delete [] nodes;

可能还有其他问题,例如:你还没有创建一个复制构造函数或赋值运算符,这样就可以使对象的副本为你删除对象。

编辑:改变了析构函数......