为了和调用析构点(Order and point of calling destructor)

2019-06-24 10:38发布

比方说,我有两个本地对象。 当函数返回时,它是保证哪一个走出去的范围的第一?

例如:

我有这样一个类:

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

Answer 1:

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

该析构函数将被称为建筑的相反顺序: m2那么m1

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

破坏的秩序是良好的规范,这样就可以依靠它。

此外,可以通过破坏在任何情况下,编译器被延迟?

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



Answer 2:

在这种情况下是重要的是明确的,而不是依靠析构函数?
不,它不是必需的。
在一个范围对象的销毁顺序被很好地定义。
它是在它们被构造的顺序的正好相反。


此外,可以通过破坏在任何情况下,编译器被延迟?
没有。
编译器不能,这是RAII的目的。 它提供了机制隐含清洁和解除分配资源,而不需要程序员的一部分的任何明确的手工工作。
你的延迟破坏的要求是平行于RAII的根本目的,它要求手动资源管理
如果您需要手动资源管理,你可以有通过分配在堆指针new和他们所指向的对象将是无效的,除非和直到您明确取消分配通过它们delete呼叫,在你给他们打电话的顺序。
的,当然,也不可取,也不鼓励这样做。



Answer 3:

破坏发生在结构的相反的顺序:第一m2然后m1

编译器不能耽误后面范围结束对象的生命周期( } )。



Answer 4:

当它超出范围的对象总是破坏 - 这是不是Java。 ˚F会得到破坏,你表示,绝不会在FUNC年底被销毁。 一般的析构函数被调用顺序相反他们的顺序施工。



文章来源: Order and point of calling destructor