【问题标题】:Timing of scope-based lock guards and return values基于作用域的锁守卫和返回值的计时
【发布时间】:2016-01-11 21:20:05
【问题描述】:
class C {
    mutable std::mutex _lock;
    map<string,string> deep_member;
public:
    auto get_big_lump()
     {
     std::unique_lock<std::mutex> lock(_lock); // establish scope guard
     return deep_member;  // copy the stuff while it can't be changed on another thread.
     }
};

关于保护和复制返回值的保证时间是什么? 是否会在持有锁时进行复制,或者在允许(或实际!)优化的情况下,是否可以在函数体返回后完成其中的一些?

【问题讨论】:

    标签: c++ scope rvo


    【解决方案1】:

    函数体终止后调用所有局部对象的析构函数。 return 语句是函数体的一部分,因此保证在执行复制时会持有锁。

    优化不会改变这一事实,它们只会改变副本的目的地 - 它可能是中间临时目的地,也可能是调用站点上的真实目的地。锁只存在于第一个副本,无论它被发送到哪里。

    但是,请记住代码中的实际范围锁定是不正确的。你需要lock_guard - 但它可能只是一个演示复制粘贴错误,而实际代码有真正的保护。

    【讨论】:

      【解决方案2】:

      std::lock 确实建立范围守卫!它只会锁定。它不解锁。你想要这个:

      std::unique_lock<std::mutex> lock(_lock);
      

      在构造时锁定并在销毁时解锁(在范围退出时发生)。

      返回值的初始化将在局部变量被销毁之前发生,因此在锁被持有时。编译器优化不允许破坏正确同步的代码。

      但是,请注意,如果返回值随后被复制或移动到某个其他变量中,则第二次复制或移动将发生在锁被释放之后。

      【讨论】:

      • 抱歉,发错了。
      • @Brian 感谢您的回答,我也需要知道这一点。如果编译器不实现这种行为,您是否知道会侵犯标准中的哪些条款?
      • @sircolinton 你到底在说哪种行为?请发布一个新的详细问题。
      • @Brian 您的回答中描述的行为。我在问您是否能够提供对标准的参考来支持您的答案。
      猜你喜欢
      • 2021-06-29
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 2016-07-31
      • 1970-01-01
      相关资源
      最近更新 更多