同步对返回值的访问 考虑以下C++成员函数: size_t size() const { boost::lock_guard<boost::mutex> lock(m_mutex); return m_size; }

同步对返回值的访问 考虑以下C++成员函数: size_t size() const { boost::lock_guard<boost::mutex> lock(m_mutex); return m_size; },c++,multithreading,boost-thread,thread-safety,C++,Multithreading,Boost Thread,Thread Safety,您的初始代码很好-存储返回值后将调用析构函数。这就是RAII的工作原理 您的第一个变体是安全的,但是您不能依赖此返回值在任何时间段内保持一致。例如,我的意思是不要在for循环中使用该返回值来迭代每个元素,因为实际大小可能会在返回后立即更改 基本上您可以这样想:返回值需要一个副本,否则将调用析构函数,因此可能会破坏返回值之前的任何内容 在return语句之后调用析构函数。 就拿这个等效的例子来说: #include <assert.h> class A { public: ~

您的初始代码很好-存储返回值后将调用析构函数。这就是RAII的工作原理

您的第一个变体是安全的,但是您不能依赖此返回值在任何时间段内保持一致。例如,我的意思是不要在for循环中使用该返回值来迭代每个元素,因为实际大小可能会在返回后立即更改

基本上您可以这样想:返回值需要一个副本,否则将调用析构函数,因此可能会破坏返回值之前的任何内容

在return语句之后调用析构函数。 就拿这个等效的例子来说:

#include <assert.h>

class A
{
public:
    ~A()
    {
        x = 10;
    }
    int x;
};

int test()
{
    A a;
    a.x = 5;
    return a.x;
}

int main(int argc, char* argv[])
{
    int x = test();
    assert(x == 5);
    return 0;
}
#包括
甲级
{
公众:
~A()
{
x=10;
}
int x;
};
int测试()
{
A A;
a、 x=5;
返回a.x;
}
int main(int argc,char*argv[])
{
int x=测试();
断言(x==5);
返回0;
}

您的两个示例构造都能满足您的需求。标准中的以下信息支持您正在寻找的行为(即使在第一个示例中):

12.4/10自毁函数:

析构函数被隐式调用。。。对于创建对象的块退出时具有自动存储持续时间(3.7.2)的构造对象

6.6/2跳转语句(其中
return
是其中之一):

从作用域退出时(无论如何完成),将为在该作用域中声明的具有自动存储持续时间(3.7.2)的所有构造对象(命名对象或临时对象)调用析构函数(12.4),顺序与其声明相反。带自动存储持续时间的初始化变量的循环外、块外或回输涉及销毁在从传输点(但不在传输点)的范围内具有自动存储持续时间的变量


因此,在返回时,
lock
变量在范围内,因此没有调用dtor。一旦执行了
返回
,就会调用
变量的dtor(从而释放锁)。

您有什么来源吗?仔细考虑后,我发现这是该行为唯一可行的方法。每个
返回表达式
隐式地将
expr
的值复制到一个临时文件中,范围内的任何对象都可以在
expr
中引用,因此它们在复制时必须仍然处于活动状态。(当然,优化可以删除副本,但其行为必须“好像”它就在那里。)我不认为你的锁真的有任何作用。只要
m_size
可以在一个原子操作中全部读取,您就会得到一个有效的值。这实际上是不能保证的。但是,使用C++0x附带的
std::atomic
可以确保在不锁定的情况下实现这一点。@Mike:锁定也是内存障碍。这是同步处理器缓存等所必需的。
#include <assert.h>

class A
{
public:
    ~A()
    {
        x = 10;
    }
    int x;
};

int test()
{
    A a;
    a.x = 5;
    return a.x;
}

int main(int argc, char* argv[])
{
    int x = test();
    assert(x == 5);
    return 0;
}