C++ 为什么std::mutex::unlock()不是noexcept

C++ 为什么std::mutex::unlock()不是noexcept,c++,c++11,mutex,destructor,raii,C++,C++11,Mutex,Destructor,Raii,为什么std::mutex::unlock()不是noexept?由于某些原因,当不拥有互斥锁的线程调用其上的unlock()时,该标准保留了未定义的行为。这样做的理由是什么?如果函数抛出,这是否会导致std::unique_lock或std::lock_guard析构函数实现意外泄漏析构函数中的异常 请注意,抛出-std::unique_lock的析构函数有一个标志,指示它是否“拥有”锁。成功调用lock后,它将设置标志。当您调用unlock时,该标志将被重置 当调用析构函数时,如果它不拥有锁

为什么
std::mutex::unlock()
不是
noexept
?由于某些原因,当不拥有互斥锁的线程调用其上的
unlock()
时,该标准保留了未定义的行为。这样做的理由是什么?如果函数抛出,这是否会导致
std::unique_lock
std::lock_guard
析构函数实现意外泄漏析构函数中的异常


请注意,抛出-

std::unique_lock
的析构函数有一个标志,指示它是否“拥有”锁。成功调用
lock
后,它将设置标志。当您调用
unlock
时,该标志将被重置


当调用析构函数时,如果它不拥有锁,它将不会调用
解锁

我不能说委员会为什么不让它成为
无例外。我只能指出一个事实,
noexcept
通常只显式地应用于整个标准库中的几个关键函数,这些函数是实现提供强大异常保证的高效函数所必需的(如
std::swap
或move构造函数)


然而,就
std::unique_lock
而言:它的析构函数(隐式地)是
noexcept
,因此如果实现允许抛出unlock,
unique\u lock
的析构函数必须在内部捕获它。

我认为这只是委员会政策的一个结果,委员会非常小心地应用noexcept,并且只在它对性能和/或实现基本/强异常保证至关重要的地方。我自己在处理代码使用中的异常安全时有这个问题mutex,特别是unlock()抛出意味着什么,以及客户端代码如何合理地处理它(特别是通过unique_lock这样的东西使用,如果unlock()异常实际发生在其析构函数中,这可能会导致终止,这很好,否则我们将违反post条件)。看起来,作为库的一个非常低级的部分,需要更好地指定它。将其与std::atomic进行比较,在后者中,一切都是正常的(正如您所期望的)。谢谢!这是正确的。但是在
lock\u guard
的情况下会发生什么呢?在
lock\u guard
的构造函数中,它
lock
互斥体,即构造函数的参数。因此,
lock\u guard
始终“拥有”互斥锁。当它破坏时,它必须
解锁它拥有的
互斥锁
BasicClockable
要求
unlock()
不抛出,因此,如果它抛出所有赌注,那么终止
实际上是一个不错的选择
unlock()
不是
noexcept
,因为它是狭义契约。尝试解锁您不拥有的互斥锁会导致UB,如果实现能够检测到异常,则可能希望抛出异常(例如,在调试模式下)。