在计算函数返回值之前或之后是否销毁了局部变量

Are locals destroyed before or after evaluation of a function return value?

本文关键字:是否 局部变量 或之后 计算 函数 返回值      更新时间:2023-10-16

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

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% 确定,如果不是,它可能会导致非常微妙、间歇性、难以发现的错误!

如果不是,那将是非常成问题的。

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

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

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

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

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

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

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