2017-08-29 182 views
7

我有以下的C++(11)代码:为什么不std :: move在std :: unique_lock上有什么作用?

#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变为“解除绑定”。

我错过了什么?

+7

'std :: move'本身并没有移动任何东西。它只是将一个左值赋给一个右值引用,使其成为移动构造函数等的一个参数。反过来,这些可能会窃取(他们认为是)临时内部的东西。但是你的代码不会调用其中的任何一个。 '解锁(std :: move(ulock));'是一个复杂的无操作。 –

+0

定义'unlock'以通过值获取'std :: unique_lock',然后进入它,以查看效果 – WhiZTiM

+3

我假设std :: move()调用了unique_lock的移动构造函数。这听起来不是这种情况...而是,'unlock()'中的右值引用是一种“通知”,它可以使用移动构造函数(如果有意义的话)。 –

回答

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

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

如果你想转让所有权,你需要一个对象,所以按价值计算,而不是按引用传递:

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

现在,你将不得不move原来的锁,因为std::unique_lock不支持复制施工,只能施工。

相关问题