移动std :: mutex的构造函数

时间:2011-09-26 15:07:34

标签: c++ c++11

c ++标准库中的许多类现在都有移动构造函数,例如 -

thread::thread(thread&& t)

但似乎std :: mutex没有。我知道它们不能被复制,但是能够从“make_mutex”函数中返回一个似乎是有意义的。 (不是说它有用,只是它有意义)

为什么std :: mutex没有移动构造函数?

2 个答案:

答案 0 :(得分:37)

嗯......主要是因为我不认为他们应该移动。从字面上看。

在某些操作系统中,互斥锁可能被建模为句柄(因此您可以复制它们),但是IIRC会对pthreads互斥锁进行就地操作。如果要重新定位,那么任何线程安全都会立即飞出窗口(其他线程如何知道互斥锁刚改变了它的内存地址......)?

答案 1 :(得分:16)

请记住,C ++不会为你不能使用的东西支付费用。哲学到心。让我们考虑一个假想的平台,它使用不透明的类型来表示互斥体;让我们调用mutex_t类型。如果在该互斥锁上运行的接口使用mutex_t*作为参数,例如void mutex_init(mutex_t* mutex);到'构造'一个互斥体,很可能就是互斥体的地址是唯一用于唯一标识互斥锁的情况。如果是这种情况,则表示mutex_t不可复制:

mutex_t kaboom()
{
    mutex_t mutex;
    mutex_init(&mutex);
    return mutex; // disaster
}

在执行mutex_t mutex = kaboom(); &mutex时,无法保证&mutex与功能块中的std::mutex值相同。

当一天实现者希望为该平台编写mutex_t时,如果要求该类型是可移动的,那么这意味着内部std::mutex必须放在动态分配的内存中,以及所有相关的处罚。

另一方面,虽然现在std::unique_ptr<std::mutex> 可移动,但很容易返回&#39;函数中的一个:返回std::mutex。这仍然支付动态分配的成本,但仅限于一个地点。所有其他不需要移动std::mutex的代码都不必支付此费用。

换句话说,由于移动互斥锁并不是互斥锁的核心操作,不需要T可移动并不能删除任何功能(感谢不可移动的 std::unique_ptr<T> =&gt; 移动 std::thread转换),与直接使用本机类型相比,开销成本最低。


join可以被类似地指定为不可移动,这将使得典型的生命周期如下:在调用有价值的构造函数之后运行(与执行的线程相关联);在调用detachstd::vector<std::thread>后,已分离/加入(与无执行线程相关联)。据我了解,EmplaceConstructible仍然可用,因为该类型应为std::thread

编辑:不正确!该类型仍然需要移动(毕竟重新分配时)。所以对我来说理由足够了:将std::vector放入std::deque和{{1}}等容器中是很典型的,因此欢迎使用该类型的功能。