【问题标题】:Order and point of calling destructor调用析构函数的顺序和点
【发布时间】:2012-05-22 15:25:51
【问题描述】:

假设我有两个本地对象。函数返回时,是否保证哪个会先出作用域?

例如:

我有这样的课:

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. 
}

【问题讨论】:

    标签: c++ compiler-construction destructor


    【解决方案1】:

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

    将按照构造的相反顺序调用析构函数:m2 然后m1

    在这种情况下,显式而不是依赖析构函数重要吗?

    破坏的顺序是明确指定的,因此您可以依赖它。

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

    没有。如果是这样,那将破坏很多基于RAII 的代码(您的MutexLock 类就是一个很好的例子)。

    【讨论】:

    • 为了支持@aix回答的第一部分,这是标准的摘录(草稿版,日期:2006-11-06 ---这方面在以后的版本中没有改变。参考资料为清楚起见而省略的部分):“在退出范围时(无论如何完成),对于在该范围中声明的所有具有自动存储持续时间的构造对象(命名对象或临时对象)调用析构函数,其声明顺序与声明的相反。 "当然,您的示例涉及自动变量声明。
    【解决方案2】:

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


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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        当对象超出范围时,它总是被销毁——这不是java。 f 将在您指定的地方被销毁,并且永远不会在 func 结束时被销毁。一般来说,析构函数的调用顺序与它们的构造顺序相反。

        【讨论】:

          猜你喜欢
          • 2013-06-24
          • 2011-01-16
          • 2018-05-08
          • 1970-01-01
          • 2010-10-13
          • 2011-11-24
          • 2013-04-14
          相关资源
          最近更新 更多