c++ 11中类型的字节对字节拷贝

Byte-for-byte copies of types in C++11?

本文关键字:字节 拷贝 类型 c++      更新时间:2023-10-16

c++ 11标准保证对于POD类型,字节对字节的复制总是有效的。但是对于某些不重要的类型呢?

下面是一个例子:

struct trivial
{
  int x;
  int y;
  trivial(int i) : x(2 * i) { std::cout << "Constructed." << std::endl; }
};

如果我复制这个结构体,字节对字节,它是保证正确复制,即使它不是技术上的POD?当不是可以对对象进行字节复制时,何时划线?

是的,保证正确复制。

引用FDIS,§3.9/2:

对于普通可复制类型 T的任何对象(基类子对象除外),无论该对象是否持有类型为T的有效值,构成该对象的底层字节都可以复制到charunsigned char数组中。如果将charunsigned char数组的内容复制回对象,则该对象随后将保持其原始值。

和§3.9/3:

对于任何普通可复制类型 T,如果指向T的两个指针分别指向T对象obj1obj2,且obj1obj2都不是基类子对象,如果构成obj1的底层字节被复制到obj2,则obj2随后将保持与obj1相同的值。

所以你问的要求是,§3.9/9:

算术类型、枚举类型、指针类型、指向成员类型的指针、std::nullptr_t以及这些类型的cv限定版本统称为标量类型。标量类型、POD类、此类类型的数组以及这些类型的cv限定的版本统称为POD类型标量类型、普通可复制类类型、此类类型的数组以及这些类型的cv限定版本统称为普通可复制类型

和§9/6:

一个平凡可复制的类是一个类,它:

  • 没有非平凡的复制构造函数,
  • 没有非平凡移动构造函数,
  • 没有非平凡的复制赋值操作符,
  • 没有非平凡的移动赋值操作符,并且
  • 有一个简单的析构函数。

c++ 11将POD类型的定义分解为更有用的类别,特别是'平凡'和'标准布局'。您的示例是标准布局,并且通常是可复制的,尽管构造函数阻止它完全平凡。一般可复制类型保证按字节安全复制:

对于任何对象(基类子对象除外可复制类型T,无论对象是否持有type的有效值T中,构成对象的底层字节(1.7)可以被复制到char或无符号char数组如果数组的内容为如果将Char或unsigned Char复制回对象,则对象应之后保持原值

因此,不需要以这种方式安全地复制POD状态,但是可以识别非POD类型的子集

如果标准声明它仅为POD类型定义(我还没有详细检查c++ 11标准,所以我不知道您的争论是否正确(a)),并且您为非POD类型这样做,它没有定义行为。时期。

它可能工作,在某些实现,在某些环境中,在一天中的某些时间,当行星对齐。它可能在绝大多数情况下都有效。如果你看重可移植性,这仍然不是一个好主意。


(a)经过进一步调查,您的情况似乎没有问题。标准的第3.9/3节(n3242草案,但如果它比这个较晚的草案改变了很多,我会感到惊讶)声明:

对于任何平凡的可复制类型T,如果两个指向T的指针分别指向不同的T对象obj1和obj2,且obj1和obj2都不是基类的子对象,如果构成obj1的底层字节被复制到obj2中,那么obj2随后将保持与obj1相同的值。

第9节(在较高的层次上)定义了"trivial copyable"的含义:

一个普通的可复制类是这样一个类:
-没有非平凡复制构造函数(12.8),
-没有非平凡移动构造函数(12.8),
-没有非平凡复制赋值操作符(13.5.3,12.8),
-没有非平凡的移动赋值操作符(13.5.3,12.8),和
-有一个简单的析构函数(12.4)。

,参考部分详细介绍了每个区域,12.8用于复制和移动类对象,13.5.3用于分配。