繁体   English   中英

调用析构函数的顺序和要点

[英]Order and point of calling destructor

可以说我有两个本地对象。 当函数返回时,是否保证哪一个将首先超出范围?

例如:

我有一个这样的课:

class MutexLock
{
    /* Automatic unlocking when MutexLock leaves a scope */
    public:
      MutexLock (Mutex &m)      { M.lock();   }
      ~MutexLock(Mutex &m)      { M.unlock(); }
};

这是一个非常常见的技巧,用于在超出范围时自动释放互斥锁。 但是如果我在范围内需要两个互斥量呢?

void *func(void *arg)
{ 
    MutexLock m1;
    MutexLock m2;

    do_work();

}  // m1 and m2 will get unlocked here. But in what order? m1 first or m2 first?

这真的不会造成任何僵局。 但是可能存在释放资源的顺序对用户有用的实例。 在这种情况下,重要的是要明确而不是依赖于析构函数?

此外,编译器在任何情况下都可以延迟销毁吗? 我的意思是

func()

{

     {
         foo f();
     } ---------> Can compiler choose to not destroy f here, rather do it at the time when func() is returning. 
}

// m1 and m2 will get unlocked here. But in what order? m1 first or m2 first?

将以与构造相反的顺序调用析构函数: m2然后是m1

在这种情况下,重要的是要明确而不是依赖于析构函数?

破坏的顺序是明确的,以便您可以依赖它。

此外,编译器在任何情况下都可以延迟销毁吗?

没有。如果确实如此,那将破坏很多基于RAII的代码(你的MutexLock类是一个非常好的例子)。

在这种情况下,重要的是要明确而不是依赖于析构函数?
不,这不是必需的。
已明确定义范围中对象的销毁顺序。
它与它们的构造顺序完全相反。


此外,编译器在任何情况下都可以延迟销毁吗?
没有。
编译器不能也就是RAII的目的。 它提供了隐式清理和释放资源的机制,而无需对程序员的任何部分进行任何明确的手动操作。
您延迟销毁的要求与RAII的目的是平行的,它要求手动资源管理
如果您需要手动资源管理,您可以通过new在堆上分配指针,并且它们指向的对象将是有效的,除非您直接通过delete调用和调用它们的顺序解除分配它们。
当然,这样做既不明智也不鼓励。

破坏以与构造相反的顺序发生:首先是m2然后是m1

编译器永远不会将对象的生命周期延迟到作用域end( } )之后。

当对象超出范围时,它总是被销毁 - 这不是java。 f在你指示的地方会被摧毁,并且在func结束时永远不会被销毁。 通常,调用析构函数的顺序与它们的构造顺序相反。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM