我有基于范围控制互斥锁定/解锁的代码:
void PerformLogin()
{
ScopeLock < Lock > LoginLock( &m_LoginLock );
doLoginCommand();
ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );
doStoreLogin();
...
}
我可以保证MemoryLock
之前LoginLock
会被破坏吗?
答案 0 :(得分:37)
是的,确实如此。在任何特定范围内,本地对象的破坏顺序与构造它们的顺序相反。
答案 1 :(得分:11)
是的,以相反的构造顺序调用析构函数。
答案 2 :(得分:11)
加上Neil的答案。
考虑相反的情况是否正确,即您无法预测堆栈声明变量的析构函数的顺序。这将使得几乎不可能在堆栈上使用依赖值类型。考虑
void Foo() {
Type1 t1;
Type2 t2(&t1);
...
}
如果C ++不能保证析构函数的排序,那么像这样的直接代码将是非常不安全的,因为在t2的析构函数运行之前t1可能会被销毁。因此,您无法保证t2的析构函数以有效的t1值运行。
答案 3 :(得分:3)
问题已经回答了,但我想补充一点,我通常习惯写这样的东西:
void PerformLogin()
{
ScopeLock < Lock > LoginLock( &m_LoginLock );
doLoginCommand();
{
ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );
doStoreLogin();
...
}
}
在我看来,这使得意图更清晰(*)。如果您的代码确实依赖特定订单,那么这可能是相关的。我发现这使得人们不太可能意外地改变顺序,并导致难以发现的错误。 (嗯,这当然不是问题,因为我们都有测试,不是吗?)
我总是用(a && b) || c
之类的东西写出冗余的括号,我发现这个问题非常相似。
(*):当然,您也可以使用评论。
答案 4 :(得分:0)
是的,析构函数与构造函数相反。因为析构函数用于删除不再需要的对象,并且构造函数用于创建对象。