【问题标题】:Can is_trivially_copy_assignable and is_trivially_copy_constructible be exploited for optimization purposes?是否可以利用 is_trivially_copy_assignable 和 is_trivially_copy_constructible 进行优化?
【发布时间】:2012-10-04 07:40:14
【问题描述】:

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

我还想知道为什么标准需要一个简单的析构函数才能使用memcpy 复制值。 (一个微不足道的析构函数确实简化了在内存中物理移动值的过程,但对于使用memcpy 复制一个值似乎不是根本必需的)。

【问题讨论】:

  • 想象析构函数做了一些工作(任何事情)。如果你只是复制(按位),那么你知道有两个对象在它们的析构函数运行时会完成这项工作。显然,该类型应该有一个重要的复制构造函数开始,但是这个对析构函数的检查可以看作是最后的手段:)
  • 如果你真的想复制一个值,那么你会期望析构函数最终运行两次。此外,如果您手动管理分配和释放,例如在容器类中,您可以在释放或重用内存之前省略对原始值的析构函数调用。

标签: c++ c++11 memcpy typetraits


【解决方案1】:

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

【讨论】:

  • 如果一个类例如,标准是否允许使用memcpy进行复制?满足std::is_trivially_copy_constructiblestd::is_trivially_copy_assignable 但不满足std::is_trivially_copyable?或者你的“当然”是什么意思。参考?
【解决方案2】:

我想知道类型特征 std::is_trivially_copy_assignablestd::is_trivially_copy_constructiblestd::is_trivially_move_assignablestd::is_trivially_move_constructible 的用途是什么,如果你不能利用它们进行初始化或使用 memcpy 赋值

它们告诉你类型的属性,这还不够吗?

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

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

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

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

【讨论】:

  • 我只是好奇是否有任何用处来了解单个方法(复制构造函数、赋值运算符等)是否微不足道。当一个类型可以简单地复制(即满足“is_trivially_copy”)或者当它保证不会抛出异常时,您可以使用它进行优化,但为什么要定义像 TrivialPair 类型这样的类型呢?
【解决方案3】:

我的猜测是,这就像标准中的任何其他挑剔一样。在某个地方,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 浮点数的机器(同样,我会真正关心)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    相关资源
    最近更新 更多