C++11 中类型的逐字节副本?

发布于 2024-12-06 15:36:17 字数 283 浏览 3 评论 0原文

C++11 标准保证逐字节复制对于 POD 类型始终有效。但是某些简单的类型呢?

下面是一个示例:

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

如果我要逐字节复制此结构,即使从技术上讲它不是 POD,是否能保证正确复制?什么时候可以确定何时不能对对象进行字节复制?

The C++11 standard guarantees that byte-for-byte copies are always valid for POD types. But what about certain trivial types?

Here's an example:

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

If I were to copy this struct, byte-for-byte, is it guaranteed to copy properly, even though it isn't technically a POD? When is the line drawn as to when it's not okay to byte-copy an object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

罪#恶を代价 2024-12-13 15:36:17

是的,保证可以正确复制。

引用 FDIS,§3.9/2:

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

和§3.9/3:

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

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

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

和§9/6:

可简单复制的类是这样的类:

  • 没有重要的复制构造函数,
  • 没有重要的移动构造函数,
  • 没有重要的复制赋值运算符,
  • 没有重要的移动赋值运算符,并且
  • 有一个简单的析构函数。

Yes, it is guaranteed to copy properly.

Quoting the FDIS, §3.9/2:

For any object (other than a base-class subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes making up the object can be copied into an array of char or unsigned char. If the content of the array of char or unsigned char is copied back into the object, the object shall subsequently hold its original value.

And §3.9/3:

For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes making up obj1 are copied into obj2, obj2 shall subsequently hold the same value as obj1.

So the requirements you're asking about are, §3.9/9:

Arithmetic types, enumeration types, pointer types, pointer to member types, std::nullptr_t, and cv-qualified versions of these types are collectively called scalar types. Scalar types, POD classes, arrays of such types and cv-qualified versions of these types are collectively called POD types. Scalar types, trivially copyable class types, arrays of such types, and cv-qualified versions of these types are collectively called trivially copyable types.

And §9/6:

A trivially copyable class is a class that:

  • has no non-trivial copy constructors,
  • has no non-trivial move constructors,
  • has no non-trivial copy assignment operators,
  • has no non-trivial move assignment operators, and
  • has a trivial destructor.
遇到 2024-12-13 15:36:17

C++11 将 POD 类型的定义分为更有用的类别,特别是“琐碎”和“标准布局”。您的示例是标准布局,并且可以简单地复制,尽管构造函数阻止它变得完全简单。保证可简单复制的类型能够安全地按字节复制:

对于任何对象(基类子对象除外)
可复制类型 T,无论该对象是否持有类型的有效值
T,构成对象的底层字节(1.7)可以复制到
一个 char 或 unsigned char.40 数组
char 或 unsigned char 被复制回对象中,该对象应
随后保持其原始值。

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

C++11 broke the definition of POD types into more useful categories, specifically 'trivial' and 'standard layout'. Your example is standard layout, and trivally copyable, although the constructor prevents it from being fully trivial. Trivially copyable types are guaranteed to be safely byte-wise copied:

For any object (other than a base-class subobject) of trivially
copyable type T, whether or not the object holds a valid value of type
T, the underlying bytes (1.7) making up the object can be copied into
an array of char or unsigned char.40 If the content of the array of
char or unsigned char is copied back into the object, the object shall
subsequently hold its original value.

So no, POD status is not required to be safely copied that way, but it is possible to identify the subset of non-POD types that can be.

莫言歌 2024-12-13 15:36:17

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

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


(a) 经过更多调查,您的具体情况似乎没有问题。标准第 3.9/3 节 (n3242 草案< /a>,但如果它与最新的草案相比发生了很大变化,我会感到惊讶)指出:

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

第 9 节(在高层次上)定义了“简单可复制”的含义:

普通可复制类是这样的类:
- 没有重要的复制构造函数(12.8),
- 没有重要的移动构造函数(12.8),
- 没有重要的复制赋值运算符(13.5.3、12.8),
- 没有重要的移动赋值运算符(13.5.3、12.8),并且
- 有一个简单的析构函数(12.4)。

引用的部分详细介绍了每个区域,12.8 用于复制和移动类对象,13.5.3 用于复制和移动类对象作业。

If the standard states it's only defined for POD types (I haven't examined the C++11 standard in detail yet so I don't know if your contention is correct or not (a)) and you do it for a non-POD type, it's not defined behaviour. Period.

It may work, on some implementations, in some environments at certain times of the day, when the planets are aligned. It may work the vast majority of times. That still doesn't make it a good idea if you value portability.


(a) After more investigation, it appears your particular case is okay. Section 3.9/3 of the standard (n3242 draft, but I'd be surprised if it had changed much from this late draft) states:

For any trivially copyable type T, if two pointers to T point to distinct T objects obj1 and obj2 where neither obj1 nor obj2 is a base-class subobject, if the underlying bytes making up obj1 are copied into obj2, obj2 shall subsequently hold the same value as obj1.

Section 9 defines (at a high level) what "trivially copyable" means:

A trivially copyable class is a class that:
- has no non-trivial copy constructors (12.8),
- has no non-trivial move constructors (12.8),
- has no non-trivial copy assignment operators (13.5.3, 12.8),
- has no non-trivial move assignment operators (13.5.3, 12.8), and
- has a trivial destructor (12.4).

with the referenced sections going into more detail on each area, 12.8 for copying and moving class objects and 13.5.3 for assignments.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文