删除派生对象时的行为

时间:2013-01-15 22:21:58

标签: c++ inheritance destructor

这是一个基于真实问题的虚构场景。如果我有基类:

class Vehicle
{
public:
     void run() { incrementStuff(); }
     virtual void incrementStuff() { } 
};

派生类:

class Car : public Vehicle
{
public:
     Car() : Vehicle() { stuff = new StuffClass(); }
     ~Car()  { delete stuff; stuff = NULL; }

     virtual void incrementStuff() { if (stuff != NULL) stuff->increment(); } 

protected:
     StuffClass* stuff;
};

然后说我有一个定期调用Vehicle :: run()的线程。我有另一个线程,最终删除指向汽车的指针。破坏的顺序将导致汽车首先被删除,然后是车辆。

如果线程(生活在Vehicle对象中)在析构函数在汽车中运行之后调用incrementStuff函数会发生什么(但显然在车辆被破坏之前)?是否会执行Car :: incrementStuff并尝试取消引用已删除的指针?或者将调用Vehicle :: incrementStuff哪个是安全的,什么都不做?

假设线程在Car ::〜Car()运行时无法调用Car :: incrementStuff(这是由互斥锁阻止的)。

这段代码已被重构以避免这种情况,但我只是想知道是否有人可以阐明它是如何工作的,或者它是否只是简单的未定义行为?

更一般地说,如果我在Car被破坏之后但在车辆出现之前尝试调用Car :: incrementStuff会发生什么? NULL检查是否有效,或者该内存是否已经解除分配并且现在可以被任何内容使用?或者,在基础对象被破坏之前,该内存是否已“释放”?

3 个答案:

答案 0 :(得分:6)

如果您删除了Car对象,则对incrementStuff()的后续调用是未定义的行为。

另外,您应该在Vehiclevirtual中制作析构函数。请参阅:When to use virtual destructors?

答案 1 :(得分:4)

你在想它。如果取消引用已经delete的指针,则调用未定义的行为。这就是你真正需要知道的。只要您致电delete ptr; ptr无效即可。

同步对此对象的访问权限。

答案 2 :(得分:2)

一个线程正在读取一个值,而另一个线程正在写入它。这是一场数据竞赛。如果两个操作未正确同步,则行为未定义。