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--这一方面在以后的版本中没有改变。为了清楚起见,省略了对章节的引用):“退出范围时(无论完成了多少),将为在该范围内声明的具有自动存储持续时间的所有构造对象(命名对象或临时对象)调用析构函数,顺序与声明的顺序相反。”当然,您的示例涉及自动变量声明。