为什么互斥量和条件变量可以微不足道地复制? [英] Why are mutexes and condition variables trivially copyable?
问题描述
LWG 2424 讨论了原子的不良状态,在C ++ 14中,互斥体和条件变量为普通可复制.我很感激,此修复程序已已排队,但 std::mutex
,
LWG 2424 discusses the undesirable status of atomics, mutexes and condition variables as trivially copyable in C++14. I appreciate that a fix is already lined up, but std::mutex
, std::condition variable
et al. appear to have non-trivial destructors. For example:
30.4.1.2.1类互斥锁[thread.mutex.class]
namespace std {
class mutex {
public:
constexpr mutex() noexcept;
~mutex(); // user-provided => non-trivial
…
}
}
这不应该使他们失去可复制的资格吗?
Shouldn't this disqualify them as trivially copyable?
推荐答案
要么是我的错误,要么是我被错误引用了,老实说我不记得是哪个.
Either it was my mistake, or I was misquoted, and I honestly don't recall which.
但是,我对此有非常强烈的建议:
However, I have this very strongly held advice on the subject:
请勿使用
is_trivial
或is_trivially_copyable
!永远!!
请使用以下其中一项:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
理论上:
tldr::请参见此优秀问题和正确答案.
没有人(包括我自己)记得is_trivial
和is_trivially_copyable
的定义.而且,如果确实要查找它,然后花10分钟对其进行分析,则它可能会或可能不会执行您直觉上认为的事情.并且,如果您设法对其进行正确分析,则CWG可能会在很少或根本没有通知的情况下更改其定义,并使您的代码无效.
No one (including myself) can remember the definition of is_trivial
and is_trivially_copyable
. And if you do happen to look it up, and then spend 10 minutes analyzing it, it may or may not do what you intuitively think it does. And if you manage to analyze it correctly, the CWG may well change its definition with little or no notice and invalidate your code.
使用is_trivial
和is_trivially_copyable
玩火.
但是这些:
is_trivially_destructible<T>
is_trivially_default_constructible<T>
is_trivially_copy_constructible<T>
is_trivially_copy_assignable<T>
is_trivially_move_constructible<T>
is_trivially_move_assignable<T>
完全按照听起来的样子做,并且不可能更改其定义.必须单独处理每个特殊成员似乎过于冗长.但这将使代码的稳定性/可靠性得到回报.而且,如果必须的话,可以将这些个体特征打包成自定义特征.
do exactly what they sound like they do, and are not likely to ever have their definition changed. It may seem overly verbose to have to deal with each of the special members individually. But it will pay off in the stability/reliability of your code. And if you must, package these individual traits up into a custom trait.
更新
例如,clang& gcc编译该程序:
For example, clang & gcc compile this program:
#include <type_traits>
template <class T>
void
test()
{
using namespace std;
static_assert(!is_trivial<T>{}, "");
static_assert( is_trivially_copyable<T>{}, "");
static_assert( is_trivially_destructible<T>{}, "");
static_assert( is_destructible<T>{}, "");
static_assert(!is_trivially_default_constructible<T>{}, "");
static_assert(!is_trivially_copy_constructible<T>{}, "");
static_assert( is_trivially_copy_assignable<T>{}, "");
static_assert(!is_trivially_move_constructible<T>{}, "");
static_assert( is_trivially_move_assignable<T>{}, "");
}
struct X
{
X(const X&) = delete;
};
int
main()
{
test<X>();
}
请注意,X
可以被复制,但是不可可以被复制.据我所知,这是合规行为.
Note that X
is trivially copyable, but not trivially copy constructible. To the best of my knowledge, this is conforming behavior.
VS-2015当前表示X
既不可复制也不可构建.我认为根据当前规范,这是错误的,但可以肯定符合我的常识告诉我.
VS-2015 currently says that X
is neither trivially copyable nor trivially copy constructible. I believe this is wrong according to the current spec, but it sure matches what my common sense tells me.
如果我需要memcpy
到未初始化的内存,我会相信is_trivially_copy_constructible
而不是is_trivially_copyable
,以确保可以进行此操作.如果我想memcpy
来初始化 内存,我会检查is_trivially_copy_assignable
.
If I needed to memcpy
to uninitialized memory, I would trust is_trivially_copy_constructible
over is_trivially_copyable
to assure me that such an operation would be ok. If I wanted to memcpy
to initialized memory, I would check is_trivially_copy_assignable
.
这篇关于为什么互斥量和条件变量可以微不足道地复制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!