22

我有根据范围控制互斥锁/解锁的代码:

void PerformLogin()
{
    ScopeLock < Lock > LoginLock( &m_LoginLock );

    doLoginCommand();

    ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );

    doStoreLogin();

    ...
}

我可以保证MemoryLock之前会被破坏LoginLock吗?

4

5 回答 5

40

是的。在任何特定范围内,本地对象都以与它们构造相反的顺序被销毁。

于 2009-08-07T16:54:47.837 回答
11

是的,析构函数的调用顺序与构造的相反。

于 2009-08-07T16:54:52.983 回答
11

补充尼尔的答案。

考虑一下是否相反,那就是您无法预测堆栈声明变量的析构函数的顺序。这将使得在堆栈上使用依赖值类型几乎是不可能的。考虑

void Foo() {
  Type1 t1;
  Type2 t2(&t1);
  ...
}

如果 C++ 不保证析构函数的顺序,那么像这样的直接代码将非常不安全,因为 t1 有可能在 t2 的析构函数运行之前被销毁。因此,您不能保证 t2 的析构函数以有效的 t1 值运行。

于 2009-08-07T16:58:58.687 回答
3

这个问题已经回答了,但我想补充一点,我通常有这样写的习惯:

void PerformLogin()
{
    ScopeLock < Lock > LoginLock( &m_LoginLock );
    doLoginCommand();

    {
        ScopeLock < SharedMemoryBase > MemoryLock( &m_SharedMemory );
        doStoreLogin();
        ...
    }
}

在我看来,这使意图更清晰(*)。如果您的代码确实依赖于特定顺序,这可能是相关的。我发现这减少了有人意外更改订单的可能性,并导致难以发现的错误。(嗯,这当然不是问题,因为我们都有测试,不是吗?)

我总是把多余的括号写成类似的东西  (a && b) || c  ,我发现这件事很相似。

(*):当然,您也可以使用注释。

于 2009-08-07T21:13:40.653 回答
0

是的,析构函数与构造函数相反。因为析构函数用于删除不再需要的对象,而构造函数用于创建对象。

于 2011-01-14T08:39:28.840 回答