对于 trivially copyable 类型,请考虑:
void f(T z)
{
T a;
T b;
std::memcpy(&b, &a, sizeof(T));
a = z;
b = z;
// ...
}
此片段的行为是否在C ++ 14中定义
假设f
传递了一个包含有效值的对象。
如果对memcpy
的调用被副本分配 b = a
取代,答案是否会更改?
结果可以转移到复制构建 T(a)
和移动构建/作业吗?
注意:与What are Aggregates and PODs and how/why are they special?相比,此问题特别关注复制不确定值的极端情况。
答案 0 :(得分:4)
这里有几件事情可以发挥作用:
unsigned char
(可能char
,如果是无符号)是例外这意味着
unsigned char
没问题,无论是使用memcpy
还是memmove
还是使用copy-assignment或copy-constructor memcpy
和memmove
大概适用于所有类型,因为结果不是由评估产生的。 (为了满足此要求,实现可以在内部使用unsigned char
,或利用针对其他类型的特定于实现的保证)当然,即使是复制不确定值的有效方法也会创建另一个不确定的值。
段落编号对应于草案n4527
答案 1 :(得分:3)
是的,它适用于所有这些案例。如果将memcpy
替换为复制分配(复制为简单的可复制类型是逐字节复制。这就是使其变得微不足道的话),并且对于所有简单的可复制类型,移动不会改变答案建筑是复制建筑,所以也没有区别。
来自[basic.types]:
对于普通可复制类型T的任何对象(基类子对象除外),是否对象 保持类型为T的有效值,组成对象的基础字节(1.7)可以复制到数组中 char或unsigned char。如果将char或unsigned char数组的内容复制回 对象,该对象随后应保持其原始值。
和
对于任何简单的可复制类型
T
,如果指向T
的两个指针指向不同的T
个对象obj1
和obj2
,其中 如果复制构成obj1
的基础字节(1.7),则obj2
和obj1
都不是基类子对象 进入obj2
,obj2
随后应与obj1
保持相同的值。 [例如:T* t1p; T* t2p; // provided that t2p points to an initialized object ... std::memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of trivially copyable type in *t1p contains // the same value as the corresponding subobject in *t2p
-end example]
其中:
算术类型(3.9.1),枚举类型,指针类型,指向成员类型的指针(3.9.2),std :: nullptr_- t和这些类型的cv限定版本(3.9.3)统称为标量类型。标量类型,POD类 (第9条),这些类型的数组和这些类型的cv限定版本(3.9.3)统称为POD 类型。 Cv不合格的标量类型,平凡的可复制类类型(第9条),此类类型的数组和非易失性 这些类型的const限定版本(3.9.3)统称为平凡可复制类型。
来自[class]的地方:
平易可复制的课程是一个类: (6.1) - 没有非平凡的复制构造函数(12.8),
(6.2) - 没有非平凡的移动构造函数(12.8),
(6.3) - 没有非平凡的文件分配操作员(13.5.3,12.8),
(6.4) - 没有非平凡的移动指派算子(13.5.3,12.8)和
(6.5) - 有一个简单的析构函数(12.4)。
因此,char
,int
和struct { int data; };
都是可复制的类型。前两个是cv不合格的标量类型,后者是一个简单的可复制类类型。