2016-07-05 64 views
3

我正在实现我自己的原子类,因为在特定项目中我无法访问C++ 11原子库。我有以下代码至今:返回值寄存器和析构函数调用顺序

class CAtomicLong 
{ 
public: 

    CAtomicLong(long lVal) : m_lValue(lVal) {} 

    long operator+(long lVal) 
    { 
     CAutoLock lock(m_lock); 
     m_lValue += lVal; 
     return m_lValue; 
    } 
private: 

    CMyMutex m_lock; 
    long m_lValue; 
}; 

假设CMyMutex是围绕一个互斥体定制的包装,并CAutoLock是一类,它的析构函数解锁其建设过程中传递给它的对象。无论如何,这些细节在很大程度上与这个问题无关。

我想知道的是,如果安全返回m_lValue这样;即将它复制到一个寄存器中以返回之前的析构函数为lock被调用?因为如果在之前调用析构函数返回寄存器被设置,另一个线程可能开始修改m_lValue,因为它正在被复制以供返回。

我已经看过在Visual Studio中对这样的代码进行反汇编,它似乎显示返回调用之前析构函数被调用,但a)我真的不知道我是什么看着大会(我还在学习:))和b)我不知道这是否是标准行为(再次,我还在学习)。最安全的解决方法,以这种潜在问题是

long operator+(long lVal) 
{ 
    CAutoLock lock(m_lock); 
    long lTemp = (m_lValue += lVal); 
    return lTemp; 
} 

...但如果这是矫枉过正,我宁愿现在知道了。

+1

你在哪个平台上?它们中的大多数都具有原子增量和获取的内在性,您可以使用它来代替互斥锁 – Dani

+0

这必须在Windows,Solaris Sparc和Linux上运行。我知道Windows上有原子递增函数,但无法找到原子检索函数,也无法访问Solaris上的必需函数。因此,这个问题。 – Wad

+0

C++中没有“寄存器”。该代码是正确的书面。 –

回答

5

您的代码是正确的。 [stmt.return]/3表示:

呼叫的结果的副本初始化是在全表达的通过返回语句,的操作数建立的端临时对象的破坏之前测序,其,然后在 之前对包含return语句的块的局部变量(6.6)进行销毁。