返回值寄存器和析构函数调用顺序

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 的析构函数之前,它会被复制到寄存器中以供返回吗? 我之所以问是因为我担心出现 torn 读写,因为如果析构函数在设置返回寄存器之前被调用,另一个线程可能会开始修改 m_lValue,因为它正在被复制以进行返回。
我已经查看了 Visual Studio 中类似于此代码的反汇编代码,并且似乎显示在调用析构函数之前进行了返回调用,但是a)我不知道汇编语言(我还在学习 :)),b)我不知道这是否是标准行为(同样,我还在学习)。避免此“潜在”问题的最安全的解决方法是
long operator+(long lVal)
{
    CAutoLock lock(m_lock);
    long lTemp = (m_lValue += lVal);
    return lTemp;
}

...但如果这太过头了,我宁愿现在知道。


1
你在哪个平台上?它们中大多数都具有原子增量和获取的内在功能,您可以使用该功能而不是互斥锁。 - Daniel
这个程序需要在Windows、Solaris Sparc和Linux上运行。我知道Windows有原子递增函数,但找不到一个原子检索函数,并且我也无法访问Solaris上所需的函数。因此提出这个问题。 - Wad
C++ 中没有“寄存器”。代码按原样编写是正确的。 - Kerrek SB
1
为什么operator+修改了类?它应该是operator+=吗? - James Adkison
@James Adkison,是的应该是+=。��错别字很好� - Wad
@Dani 如果你有任何关于原子操作的更多信息,可能对我其他的问题有用,请在那里发布。 - Wad
1个回答

6

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

调用结果的复制初始化在return语句操作数建立的完整表达式结束时临时对象的销毁之前被排序,这反过来又在包含return语句的块的局部变量(6.6)的销毁之前被排序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接