8

我正在考虑创建一个表示同步原语所有权的类,如下所示:

class CCriticalSectionLock
{
public:
    CCriticalSectionLock( CCriticalSection &cs ) : cs( cs )
    { cs.Enter(); }
    ~CCriticalSectionLock()
    { cs.Leave(); }
private:
    CCriticalSection &cs;
};

这看起来是一种能够在函数期间取得所有权并确保所有权被释放的好方法,即使存在多个退出点或异常也是如此。然而,它确实引发了一些微妙的问题,即编译器何时会对各种事物进行评估。考虑以下用途:

int MyMethod( void )
{
    not_locked(); // do something not under lock

    CCriticalSectionLock myLock( someCriticalSection );

    locked(); // do something under lock

    return ...; // some expression
}

AFAIK,C++ 生命周期规则将保证在获取锁之前not_locked()调用它,并且在持有锁时调用它。locked()

但是,我不太清楚的是,何时返回的表达式将相对于调用锁析构函数的点进行评估。是否保证表达式将在析构函数之前被评估?我会这么认为,但我不是 100% 确定,否则可能会导致非常微妙、间歇性、难以发现的错误!

4

1 回答 1

8

如果他们不是,那将是非常有问题的。

实际上,请考虑以下代码:

int function(){

    MyClass myObject;
    //stuff
    return 5 + myObject.getNumericalValue();
}

使用getNumericalValue()一个简单的成员函数,该函数根据成员变量的计算返回一个 int。如果在销毁 后评估表达式myObject,您将有未定义的行为,并且在 return 语句中使用本地是不可能的(事实并非如此)。

在您的情况下,在评估 return 语句,锁将被销毁。

为了增加一些严格性,让我引用标准(§3.7.3/3,强调我的):

如果具有自动存储持续时间的变量具有初始化或具有副作用的析构函数,则不应在其块结束之前将其销毁,即使看起来未使用也不应作为优化消除

对于函数,块的结尾在 return 语句之后。

于 2013-09-27T08:59:30.857 回答