为什么C ++ 11的POD“标准布局”定义的方式是什么? [英] Why is C++11's POD "standard layout" definition the way it is?

查看:201
本文介绍了为什么C ++ 11的POD“标准布局”定义的方式是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C中寻找新的,轻松的POD定义++ 11 (第9.7节)


标准布局类是一个类:

A standard-layout class is a class that:


  • 没有类型为非标准布局类(或此类类型的数组)或引用的非静态数据成员,

  • 没有虚拟函数(10.3)和没有虚拟基类(10.1),

  • 对所有非静态数据具有相同的访问控制成员

  • 没有非标准布局基类,

  • 在大多数派生类中没有非静态数据成员,最多一个具有非静态数据成员的基类,或者没有具有非静态数据成员的基类,

  • 没有与第一个非静态数据成员的类型相同。

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

如果我们允许数据成员使用不同的访问控制,会出什么问题?

What would go wrong if we tolerated data members with varying access controls?

如果第一个数据成员也是基类,会出错什么?即

What would go wrong if the first data member was also a base class? i.e.

struct Foo {};
struct Good : Foo {int x; Foo y;};
struct Bad  : Foo {Foo y; int x;};

我承认这是一个奇怪的构造,但为什么被禁止,但不是

I admit it's a weird construction, but why should Bad be prohibited but not Good?

最后,数据成员?

推荐答案

您可以将标准布局类对象地址转换为指向其第一个成员的指针,后面的段落,这也经常在C:

You are allowed to cast a standard layout class object address to a pointer to its first member and back by one of the later paragraphs, which is also often done in C:

struct A { int x; };
A a;

// "px" is guaranteed to point to a.x
int *px = (int*) &a;

// guaranteed to point to a
A *pa = (A*)px; 

为了工作,第一个成员和完整的对象必须有相同的地址不能通过任何字节来调整int指针,因为它不知道它是否是 A 的成员)。

For that to work, the first member and the complete object have to have the same address (the compiler cannot adjust the int pointer by any bytes because it can't know whether it's a member of an A or not).


最后,如果多个成员类有数据成员,会出现什么问题?

Finally, what would go wrong if more than one constituent class had data members?

在类中,根据声明顺序将成员分配到增加的地址中。然而,C ++并不规定在类之间的数据成员的分配顺序。如果派生类和基类都具有数据成员,则标准不会有意地为它们的地址定义顺序,以便在布局存储器时给予实现完全的灵活性。但是对于上面的转换工作,你需要知道什么是分配顺序中的第一成员!

Within a class, members are allocated in increasing addresses according to the declaration order. However C++ doesn't dictate the order of allocation for data members across classes. If both the derived class and base class had data members, the Standard doesn't define an order for their addresses on purpose, so as to give an implementation full flexibility in layouting memory. But for the above cast to work, you need to know what is the "first" member in allocation order!


第一个数据成员也是一个基类?

What would go wrong if the first data member was also a base class?

如果基类与第一个数据成员具有相同的类型,在存储器中的派生类对象之前的基类将需要在存储器中的派生类对象数据成员之前具有填充字节(基本类将具有大小1),以避免对于基类和第一数据具有相同的地址成员(在C ++中,同一类型的两个不同对象总是有不同的地址)。但是,这又不可能将派生类对象的地址转换为其第一个数据成员的类型。

If the base class has the same type as the first data member, implementations that place the base classes before the derived class objects in memory would need to have a padding byte before the derived class object data members in memory (base class would have size one), to avoid having the same address for both the base class and the first data member (in C++, two distinct objects of the same type always have different addresses). But that would again make impossible to cast the address of the derived class object to the type of its first data member.

这篇关于为什么C ++ 11的POD“标准布局”定义的方式是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆