什么时候c ++ 11中的类型允许记忆?

Ger*_*ago 23 c++ memory c++11

我的问题如下:

如果我想复制类类型,memcpy可以非常快速地完成.在某些情况下允许这样做.

我们有一些类型特征:

  • is_standard_layout.
  • is_trivially_copyable.

我想知道的是当类型是"可按位复制"时的确切要求.

我的结论是,如果两个is_trivally_copyableis_standard_layout特征都为真,则类型是按位可复制的:

  1. 这正是我需要按位复制的内容吗?
  2. 是否过度约束?
  3. 它不受约束吗?

PS:当然,memcpy的结果必须正确.我知道我可以在任何情况下记忆,但不正确.

bam*_*s53 19

如果memcpy为true ,则可以使用memcpy复制类型为T的对象.该类型不特别需要是标准布局类型."平凡可复制"的定义基本上是这样做的安全.

使用memcpy进行复制但不是标准布局的类的示例:

struct T {
  int i;
private:
  int j;
};
Run Code Online (Sandbox Code Playgroud)

因为此类对不同的非静态数据成员使用不同的访问控制,所以它不是标准布局,但它仍然可以轻易地复制.

  • @GermánDiago不,您可以使用非标准布局的简单可复制类型。 (2认同)

Seb*_*ach 9

如果is_trivally_copyable<T>::value(或在C++ 14中is_trivially_copyable<T>())不为零,则类型可以使用复制memcpy.

根据C++标准,可轻松复制的类型意味着:

构成对象的底层字节可以复制到char或unsigned char数组中.如果将char或unsigned char数组的内容复制回对象,则该对象应随后保持其原始值.

但是,重要的是要意识到指针也是简单的可复制类型.每当你要复制的数据结构中有指针时,你必须在脑力上确保复制它们是正确的.

仅仅依赖于可轻易复制的对象可能导致危险的示例:

  • 树结构实现,其中数据放置在连续的内存区域中,但节点存储子节点的绝对地址
  • 为了多线程性能而创建一些数据的多个实例(为了减少缓存崩溃),内部拥有指针,指向任何地方
  • 你有一个没有指针的扁平物体,但内部嵌入了第三方结构.未来某个时刻的第三方结构包括一个不应该存在两次或更多次的指针.

因此,无论何时进行memcopying,请记住检查是否可以在特定情况下复制指针,以及是否可以.

在编译器用语中意识到这is_trivially_copyable只是"语法检查",而不是"语义测试".


R S*_*ahu 7

来自http://en.cppreference.com/w/cpp/types/is_trivially_copyable:

普通可复制类型的对象是唯一可以安全地与std::memcpy二进制文件一起复制或序列化的C++对象std::ofstream::write()/std::ifstream::read().通常,一个简单的可复制类型是任何类型,其底层字节可以复制到char或unsigned char数组并复制到相同类型的新对象中,并且生成的对象将具有与原始对象相同的值.


Nik*_*iou 5

具有普通拷贝构造函数,普通拷贝赋值运算符和普通析构函数的对象可以用memcpy或复制memmove

对一个类的特殊成员函数的要求T是微不足道的

复制构造函数(cc)和复制赋值运算符(ca)

  • 不是用户提供的(意思是,它是隐式定义的或默认的),如果它是默认的,它的签名与隐式定义的相同
  • T没有虚成员函数
  • T没有虚基类
  • 为每个直接基础选择的cc/ca T微不足道的
  • 为每个非静态类类型(或类类型数组)选择的cc/ca T微不足道的
  • T没有volatile限定类型的非静态数据成员(自C++ 14以来)

析构函数

  • 不是用户提供的(意思是,它是隐式定义或默认的)
  • 不是虚拟的(也就是说,基类析构函数不是虚拟的)
  • 所有直接基类都有微不足道的析构函数
  • 类类型(或类类型数组)的所有非静态数据成员都具有简单的析构函数

只是声明函数= default不会使它变得微不足道(如果类也支持相应函数的所有其他条件是微不足道的,那将只是微不足道)但是在用户代码中显式写入函数确实可以防止它变得微不足道.还用C语言兼容所有数据类型(POD类型)是平凡可复制.

来源:C++并发实施和cppreference.com

  • @GermánDiago:如果析构函数不是微不足道的,那么您就没有正确销毁目标位置存在的对象(如果存在)(也就是说,您没有将 `memcpy` 放入 `char` 数组来创建新的“目的”)。 (2认同)