【问题标题】:Why has a class to be std::is_trivially_copyable and not std::is_trivially_copy_constructible to be useable with memcpy为什么有一个类是 std::is_trivially_copyable 而不是 std::is_trivially_copy_constructible 可用于 memcpy
【发布时间】:2016-02-03 23:32:52
【问题描述】:

根据各种来源(例如cppreference.com),一个类必须可以简单地复制才能与 memcpy 一起使用,但我不明白为什么简单地复制可构造类是不够的。 只要我确保在适当的时间调用析构函数,普通可复制类的额外属性(如普通析构函数)就无关紧要了。

谁能提供一个例子或解释,当在一个类上使用 memcpy 时,例如一个非平凡的析构函数(或移动构造函数)会导致问题?

【问题讨论】:

  • 如果你已经有一个现有的对象,那么用memcpy 改变它的值不是构造,它更接近于赋值。所以认为只有复制构造函数很重要是错误的。
  • @jonathan-wakely 我没有现有的对象,我只有一些内存。从概念上讲,它类似于放置新。
  • 那么您是否建议应该为您现在拥有的特定用例量身定制语言规则?这些规则包括将现有对象复制到未初始化的内存,但它们也包括将现有对象复制到另一个现有对象。仅仅因为您现在只关心第一种情况并不意味着规则是错误的。
  • 如果你想初始化原始内存,那么placement new有什么问题呢?为什么memcpy 更可取?
  • @jonathan-wakely 我有点想知道 is_trivially_copy_constructible 到底有什么用处,如果不是我的用例的话。如果/我的用例会遇到麻烦。

标签: c++


【解决方案1】:

普通可复制类的额外属性(如普通析构函数)无关紧要,只要我确保在适当的时间调用析构函数即可。

不过,这是一个很大的“如果”,不是吗?这些规则旨在保护您免于调用 UB,如果按位复制需要非平凡破坏的对象是合法的,这将非常容易。然后......那个不平凡的析构函数做了什么? delete 现在共享的资源?这只是在乞求三法则的问题。

如果你想复制一个管理资源的复杂对象,你真的应该正确地复制它,使用复制构造函数。 std::memcpy 是为了向后兼容而提供的,并且只能用于没有其他对象要管理的对象。因为那是疯狂的谎言。

【讨论】:

  • 它不再像aligned_storage 那样危险。例如,密码类(带有嵌入式密码)可以在其析构函数中调用 memset,以防止纯文本密码在内存中停留无限时间。
  • @SananeLan:是的,它可以。但是作为语言规范的作者,为什么要不遗余力地允许比你实际需要的更危险的事情呢?作为 OP,为什么需要 std::memcpy 一个非平凡的类型?你知道,你不妨发布一个新的 SO 问题,询问为什么我们需要构造函数和析构函数,因为你可以手动清理所有内容,对吧?
猜你喜欢
  • 2013-05-08
  • 2017-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-07
相关资源
最近更新 更多