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
的有效值,构成该对象的底层字节都可以复制到char
或unsigned char
数组中。如果将char
或unsigned char
数组的内容复制回对象,则该对象随后将保持其原始值。
和§3.9/3:
对于任何普通可复制类型
T
,如果指向T
的两个指针分别指向T
对象obj1
和obj2
,且obj1
和obj2
都不是基类子对象,如果构成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
用于分配。