Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调用析构函数的顺序和点_C++_Compiler Construction_Destructor - Fatal编程技术网

C++ 调用析构函数的顺序和点

C++ 调用析构函数的顺序和点,c++,compiler-construction,destructor,C++,Compiler Construction,Destructor,假设我有两个局部对象。当函数返回时,是否保证哪一个将首先超出范围 例如: 我有一门课是这样的: class MutexLock { /* Automatic unlocking when MutexLock leaves a scope */ public: MutexLock (Mutex &m) { M.lock(); } ~MutexLock(Mutex &m) { M.unlock(); } }; 这是一个

假设我有两个局部对象。当函数返回时,是否保证哪一个将首先超出范围

例如:

我有一门课是这样的:

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和m2将在此处解锁。但顺序是什么?m1优先还是m2优先?

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

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

毁灭的顺序是明确的,因此你可以信赖它

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


不。如果它这样做了,就会破坏很多基于的代码(你的
MutexLock
类就是一个很好的例子)。

破坏按相反的顺序发生:首先
m2
然后
m1


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

当对象超出作用域时,它总是被销毁-这不是java。f将在您指定的位置被销毁,并且在func结束时永远不会被销毁。通常,析构函数的调用顺序与其构造顺序相反。

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


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

当然,这样做既不可取,也不鼓励这样做。

为了支持@aix答案的第一部分,这是标准的一个摘录(草案版本,日期:2006-11-06--这一方面在以后的版本中没有改变。为了清楚起见,省略了对章节的引用):“退出范围时(无论完成了多少),将为在该范围内声明的具有自动存储持续时间的所有构造对象(命名对象或临时对象)调用析构函数,顺序与声明的顺序相反。”当然,您的示例涉及自动变量声明。