本地人在评估函数返回值之前还是之后被销毁?

2022-01-19 00:00:00 return destructor c++ object-lifetime

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

I am thinking of making a class which represents ownership of a synchronization primitive, something like this:

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

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

This looks like a good way to be able to take ownership during a function and ensure ownership is released even if there are multiple exit points or exceptions. It does, however, raise some subtle issues about exactly when the compiler will have various things evaluated. Consider the following use:

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() 将被调用 before 锁定,并且 locked() 将在持有锁时调用.

AFAIK, C++ lifetime rules would guarantee that not_locked() would be called before the lock is taken, and that locked() would be called while the lock is held.

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

However, what I am not so clear on is exactly when the expression being returned would be evaluated with respect to the point at which the lock destructor is called. Is it guaranteed that the expression will be evaluated before the destructor? I would think so but I'm not 100% sure, and if not it could lead to very subtle, intermittent, hard-to-find bugs!

推荐答案

如果不是,那将是非常有问题的.

If they weren't, that would be very problematic.

确实,请考虑以下代码:

Indeed, consider the following code :

int function(){

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

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

with getNumericalValue() a simple member function that returns an int based on computations on member variable. If the expression was evaluated after the destruction of myObject, you would have undefined behavior, and using locals would be impossible in return statement (which isn't the case).

在您的情况下,锁将在返回语句评估后被销毁.

In your case, the lock will be destroyed after the evaluation of the return statement.

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

To add some strictness to that, let me quote the standard (§3.7.3/3, emphasis mine) :

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

If a variable with automatic storage duration has initialization or a destructor with side effects, it shall not be destroyed before the end of its block, nor shall it be eliminated as an optimization even if it appears to be unused

对于一个函数来说,块的结束是在返回语句之后.

The end of the block, for a function, is after the return statement.

相关文章