按值返回由互斥锁保护的shared_ptr是否安全?

时间:2011-10-06 16:48:52

标签: c++ gcc shared-ptr

以下是代码示例:

class A {
  boost::mutex a_mutex;
  boost::shared_ptr<int> a;

  boost::shared_ptr<int> clone_a(void) {
    boost::lock_guard<boost::mutex> lock(a_mutex);
    return a;
  }
};

建议尽管编译器优化,但boost::shared_ptr上的A::a拷贝构造函数调用将在boost::lock_guard析构函数调用之前。 那么,拨打A::clone_a()是否安全?

3 个答案:

答案 0 :(得分:5)

如果“安全”,则表示您不会在a上获得数据竞赛,那么是。就像你说的那样。

然而,正如您可能知道的那样,它不会保护对*a(或*clone_a())的进一步访问。我不确定,为什么这个方法称为“克隆”,因为它不会克隆任何东西。

答案 1 :(得分:2)

是的,这段代码是安全的。如果你引用shread_ptr Thread-Safety,你可以看到对线程局部shared_ptr对象的线程写访问就好了。

在上面的代码中,对成员shared_ptr的访问需要锁定,因为它可以被多个线程访问。返回临时的副本是在锁内完成的,因此你在那里安全。其他线程无法看到该临时值,因此您可以安全地将其复制到其他shared_ptr中。

现在,选择clone_a作为函数名称可能是错误的。您没有克隆底层对象,您只是获取shared_ptr的副本。所以我假设您打算共享相同的底层“int”。

答案 2 :(得分:-1)

如果您使用返回值,则不会。返回值本身是一个 临时的,其寿命超出了函数的末尾;它 将在调用的完整表达式结束时被破坏 A::clone_a。所以如果你写的东西如下:

shared_ptr<int> newA = object->clone_a();

,形式语义将由临时返回 要object->clone_a()复制到newA,请将其复制到-D somthing 调用者(因此不受互斥锁保护)。在这种特殊情况下,你 可能因为RVO而侥幸逃脱,但这不一定是 案例,还有其他情况,RVO无法干预。

如果你担心的只是指针的副本,我很确定 如果您设置了正确的编译器选项(boost::shared_ptr),{{1}}将以原子方式运行。在 在这种情况下,您根本不需要互斥锁。