似乎用memcpy
复制值是不安全的,除非该类型可以轻易复制,即满足std::is_trivially_copyable
类型特征。我想知道类型特征std::is_trivially_copy_assignable
,std::is_trivially_copy_constructible
,std::is_trivially_move_assignable
和std::is_trivially_move_constructible
的目的是什么,如果您不能利用它们进行初始化或使用memcpy
进行分配。他们是否允许其他优化?
我也想知道为什么标准需要一个简单的析构函数来使值memcpy
可复制。 (一个简单的析构函数确实简化了在内存中物理移动值的过程,但对于仅使用memcpy
重复一个值来说,它似乎并不是必需的。
答案 0 :(得分:2)
我想知道类型特征的目的是
std::is_trivially_copy_assignable
,std::is_trivially_copy_constructible
,std::is_trivially_move_assignable
和std::is_trivially_move_constructible
,如果你不能利用它们进行初始化或赋值{{1 }}
他们告诉你这种类型的属性,还不足以存在吗?
你可能有一个类型,它有一个简单的复制构造函数,但是一个非平凡的移动构造函数,所以它不符合一个简单的可复制类型,但是可以简单地复制构造。
使用这种类型时,您可以使用SFINAE或其他静态多态来启用/禁用某些操作,除非它们保证是微不足道的。例如,想象一个类模板memcpy
,如果TrivialPair<A,B>
和A
不是简单地移动可构造的,那么它可以将其移动构造函数声明为已删除,并且类似于其他操作。这意味着B
仅支持TrivialPair
和A
都支持且不会调用任何非平凡函数的操作。
我也想知道为什么标准需要一个简单的析构函数来使值
B
可以复制
“平凡可复制”可以被认为是说类型只是一堆字节,即只是可以安全地复制到存储器中的另一个地方并且不改变该值的数据。如果类型有一个非平凡的析构函数,那么它不仅仅是一堆字节,它还有一些编译器无法理解的额外行为,这可能会使memcpy
使用不安全。
答案 1 :(得分:1)
不确定。可以编写一个利用它的向量类模板,并在其复制构造函数中调用std :: memcpy,以防它安全。我相信至少有一个std :: copy的实现对于迭代器类型为T *并且T可以轻易复制的情况采用类似的优化。
答案 2 :(得分:0)
我的猜测是,这就像标准中的任何其他挑剔一样。在某处,Joe和Jane将谈论一个字符是8位的,而Bob会大肆宣传该标准是如何说它实际上是“8位或更多位!”第二天,他们将通过将浮动复制到uint32_t并根据IEEE-754做一些小事来做一些类型的惩罚hackery,Bob将再次大喊大叫IEEE-754是如何严格要求的,并且他会坚持认为,他们所做的事情可能会导致一些理论机器在那里破坏宇宙。
该死的鲍勃!在实践中,显而易见的是,std :: is_trivially_copy_assignable意味着表达式“A = B”将仅评估为memcpy(),因此请继续使用。当然可能有一些模糊的实现,当你memcpy()一个非严格std :: is_trivially_copyable的类型时,它会给你一个指责,我确信Bob可能是所述实现的作者,但你真的在乎吗?
这只是我的猜测,请注意。我在这方面有一些适度的经验,但我绝不是C ++细节的世界级专家。如果我错了(实际上,不仅仅是理论上的),请随时告诉我。我也很想看到一台带有CHAR_BIT&gt;的机器。 8(我实际上会关心),或者是非IEEE-754花车的机器(再次,我实际上会关心它)。