2013-09-27 58 views
7

我想到做这代表了同步的所有权原始的,像这样一类:本地人在评估函数返回值之前还是之后被销毁?

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 
} 

据我所知,C++一生规则将保证not_locked()将之前被称为锁被采取,并且当锁被认为locked()将被调用。

然而,什么我不是很清楚是什么时候返回的表达式将被评估相对于在上述锁定调用析构函数点。是否保证表达式在之前将被评估为?我会这样想,但我不是100%肯定的,如果不是这样,它可能会导致非常微妙的,间歇性的,难以发现的错误!

+0

重复:[什么是第一次 - 堆栈展开或复制返回值](http://stackoverflow.com/q/8923018/220636) – nabulke

+0

@nabulke所以这就是为什么我没有找到任何东西...我是寻找破坏/评估,但隐藏在展开/复制下。 – Kevin

回答

5

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

实际上,考虑下面的代码:

int function(){ 

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

getNumericalValue()返回基于成员变量计算一个int一个简单的成员函数。如果在销毁myObject之后评估表达式,那么您将会遇到未定义的行为,并且在返回语句中使用本地语言是不可能的(情况并非如此)。

在你的情况下,锁定将被销毁评估返回声明。

要严格一些添加到,请允许我引用的标准(§3.7.3/ 3,重点煤矿):

如果具有自动存储持续时间的变量初始化或有副作用的析构函数, 不得 其块结束前被破坏,也不应被消除作为优化即使它似乎 是未使用

块的端部,对于一个功能,是船尾呃返回声明。

+0

能够在返回中使用本地的好处;我也曾考虑过,但是想知道如果任何优化能够在返回没有引用本地的情况下重新排序。 – Kevin

+0

我对编译器知之甚少,但是对于编译器我知道的很少,但是会做出这样的假设的人(比如“本地没有用在return语句中,我可以在语句之前销毁它)远离...在这种情况下,它显然是一个不兼容的编译器。 – JBL

相关问题