0

memcpy除非类型是可简单复制的,即满足std::is_trivially_copyable类型特征,否则值似乎不安全复制。我想知道类型特征std::is_trivially_copy_assignable,和的目的是什么std::is_trivially_copy_constructible,如果你不能利用它们进行初始化或赋值。他们允许其他优化吗?std::is_trivially_move_assignablestd::is_trivially_move_constructiblememcpy

我还想知道为什么标准需要一个简单的析构函数来使值可以用memcpy. (一个微不足道的析构函数确实简化了在内存中物理移动一个值,但它似乎根本不需要用 复制一个值memcpy)。

4

3 回答 3

3

我想知道类型特征std::is_trivially_copy_assignable,的目的是什么std::is_trivially_copy_constructiblestd::is_trivially_move_assignable以及std::is_trivially_move_constructible是否不能利用它们进行初始化或赋值memcpy

他们告诉你类型的属性,这还不够存在的理由吗?

你可能有一个类型,它有一个普通的复制构造函数,但有一个非普通的移动构造函数,所以它不符合普通可复制类型,但可以普通复制构造。

使用这种类型时,您可以使用 SFINAE 或其他静态多态性来启用/禁用某些操作,除非它们被保证是微不足道的。例如,假设一个类模板TrivialPair<A,B>可以将其移动构造函数声明为已删除,如果A并且B不是普通可移动构造函数,其他操作也类似。这意味着TrivialPair它只支持既支持又不调用任何重要函数的操作AB

我还想知道为什么标准需要一个简单的析构函数才能复制值memcpy

“可简单复制”可以被认为是说类型只是一堆字节,即只是可以安全地复制到内存中另一个位置且不改变值的数据。如果该类型有一个重要的析构函数,那么它不仅仅是一堆字节,它还有一些编译器无法理解的额外行为,这可能会使 usingmemcpy不安全。

于 2012-10-13T21:25:04.943 回答
1

当然。可以编写一个向量类模板,利用它并​​在其复制构造函数中调用 std::memcpy,以防万一这样做是安全的。我相信 std::copy 的至少一种实现对迭代器类型为 T* 且 T 可轻松复制的情况采用了类似的优化。

于 2012-10-13T21:18:50.873 回答
-1

我的猜测是,这就像标准中的任何其他挑剔一样。在某个地方,Joe 和 Jane 会谈论一个 char 是 8 位的,而 Bob 会进来大喊标准如何说它实际上是“8 位或更多位!” 第二天,他们将通过将浮点数复制到 uint32_t 并根据 IEEE-754 进行一些操作来做一些类型的双关语黑客,Bob 将再次进来大喊如何不严格要求 IEEE-754,并且他会坚持认为他们正在做的那些小玩意可能会导致一些理论机器在那里爆炸宇宙。

该死的鲍勃!

在实践中,很明显 std::is_trivially_copy_assignable 意味着表达式“A = B”只会计算为 memcpy(),所以继续利用。当然,当你 memcpy() 一个不是严格 std::is_trivially_copyable 的类型时,可能会有一些晦涩难懂的实现给你指指点点,我敢肯定 Bob 可能是上述实现的作者,但你真的在乎吗?

这只是我的猜测,请注意。我在这方面有一些经验,但我绝不是 C++ 细节方面的世界级专家。如果我对此有误(在实践中,而不仅仅是在理论上),请随时告诉我。我也很想看到一台 CHAR_BIT > 8 的机器(我实际上会关心),或者一台具有非 IEEE-754 浮点数的机器(同样,我实际上会关心)。

于 2017-07-17T02:37:31.913 回答