【问题标题】:Why doesn't std::move on a std::unique_lock have any effect?为什么 std::move 在 std::unique_lock 上没有任何效果?
【发布时间】:2018-02-07 09:08:56
【问题描述】:

我有以下 C++(11) 代码:

#include <mutex>

void unlock(std::unique_lock<std::mutex> && ulock)
{
}

int main(void)
{
    std::mutex m;
    std::unique_lock<std::mutex> ulock(m);

    unlock(std::move(ulock));

    if (ulock.mutex() == &m || ulock.owns_lock())
    {
        throw std::runtime_error("");
    }

    return 0;
}

我想不通的是为什么互斥锁在从unlock() 返回后仍然保留。我的期望是std::move() 导致锁在从对unlock() 的调用返回时超出范围(并被析构函数解锁)。至少,std::move() 似乎应该导致ulock 从互斥锁m 中“未绑定”。

我错过了什么?

【问题讨论】:

  • std::move 本身不会在任何地方移动任何东西。它只是将左值转换为右值引用,允许它成为移动构造函数等的参数。反过来,那些人可能会窃取(他们认为是)临时的内部结构。但是您的代码没有调用它们中的任何一个。 unlock(std::move(ulock)); 是一个精心设计的无操作。
  • 定义unlockstd::unique_lock的值,然后移入其中,查看效果
  • 我假设 std::move() 为 unique_lock 调用了移动构造函数。听起来情况并非如此......相反,unlock() 中的右值引用是一种“通知”,it 可以使用移动构造函数(如果这有意义的话) .
  • 是的,没错。 std::move 是移动的许可,而不是其行为。 std::move(T&amp; v) 只是做return static_cast&lt;T&amp;&amp;&gt;(v); 而已。
  • @IgorTandetnik:您应该(已经)发布(编辑)您的评论作为答案。我会接受,因为你是第一个。

标签: c++ c++11 mutex move-semantics


【解决方案1】:
void unlock(std::unique_lock<std::mutex> && ulock)

这里ulock 是一个参考。一种特殊的参考,但仍然是参考。它只是另一个对象的别名。它的创建不涉及创建新对象或任何类型的所有权转移。同样,它的生命周期结束不会导致任何析构函数调用,它只是意味着您丢失了引用其他对象的别名(这并不重要,因为函数无论如何都会结束)。

如果你想转移所有权,你需要一个对象,所以通过值而不是通过引用来传递:

void unlock(std::unique_lock<std::mutex> ulock)

现在,你将不得不move原来的锁,因为std::unique_lock不支持复制构造,只支持移动构造。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 2021-08-17
    • 2012-10-17
    • 2020-12-23
    • 2012-07-28
    • 2016-12-05
    相关资源
    最近更新 更多