存储的结构/对象内部顺序(Order of storage inside a structure /

2019-06-26 01:32发布

考虑以下两种情况:

struct customType
{
   dataType1 var1; 
   dataType2 var2;
   dataType3 var3;
} ;

customType instance1;
// Assume var1, var2 and var3 were initialized to some valid values.

customType * instance2 = &instance1;    
dataType1 firstMemberInsideStruct = (dataType1)(*instance2);

class CustomType
{
   public:
       dataType1 member1;
       dataType2 member2;

       retrunType1 memberFunction1();

   private:
       dataType3 member3;
       dataType4 member4;

       retrunType2 memberFunction2();
};

customType object;
// Assume member1, member2, member3 and member4 were initialized to some valid values.

customType *pointerToAnObject = &object ;
dataType1 firstMemberInTheObject = (dataType1) (*pointerToAnObject);

它是始终可以安全地做到这一点?

我想知道,如果标准规定中存储的任何命令 -

  1. C结构内的元素。
  2. 一个C ++类的对象内部的数据成员。

Answer 1:

C99和C ++有关此不同比特。

C99标准保证一个结构的字段将在它们被声明的顺序存储器来布置,并且两个相同结构的字段将具有相同的偏移量。 见这个问题为C99标准的相关章节。 总结:该第一场的偏移量指定为零,但是偏移量后,可以进行不是由标准指定。 这是为了允许C编译器来调节每个字段的偏移量等等领域将满足该架构的任何存储器对齐要求。 因为这是依赖于实现的,C提供了一个标准的方法来确定使用每个字段的偏移offsetof宏。

C ++提供了这种保证只对普通旧数据(POD) 。 不属于普通的旧数据C ++类不能像这样进行处理。 该标准给出了C ++编译器相当多的自由在上课的时候使用了多重继承,具有非公共字段或成员,或包含虚拟成员是如何组织的一类。

这意味着你的例子:

dataType1 firstMemberInsideStruct = (dataType1)(*instance2);

这条线路是好的, 只有 dataType1,dataType2和dataType3是普通的旧数据。 如果其中任何一个都没有,那么customType结构不能有一个简单的构造函数(或析构函数)和这个假设可能不成立。

dataType1 firstMemberInTheObject = (dataType1) (*pointerToAnObject);

无论此行是不是安全dataType1dataType2dataType3是POD,因为CustomType类有私有的实例变量。 这使得它不是一个POD类,所以你不能假设它的第一个实例变量会以特定的方式进行排序。



Answer 2:

9.0.7

一个标准的布局类是一类: - 具有式非标准布局类(或这些类型的阵列)或参考的没有非静态数据成员, - 没有虚函数(10.3),并且没有虚基类( 10.1), - 具有用于所有非静态数据成员相同的访问控制(第11), - 没有非标准布局基类, - 或者具有在最派生类和至多一个没有非静态数据成员基类与非静态数据成员,或具有与非静态数据成员没有基类,以及 - 具有相同类型的无基类作为第一非静态数据member.108

9.2.14

具有相同的访问控制(第11)(非联合)类的非静态数据成员被分配,使得后来构件具有类对象内的较高地址。 与不同的访问控制非静态数据成员的分配顺序是不确定的(11)。 实施对齐要求可能会导致相邻的两个不被后对方立即分配; 所以对于空间可能要求用于管理虚拟功能(10.3)和虚基类(10.1)。

9.2.20

指向一个标准布局结构对象,使用的reinterpret_cast适当转换,点到它的初始成员(或如果该构件是一个位域,然后在它所在的单元),并且反之亦然。 [注:因此,有可能是一个标准的布局结构对象中未命名的填充,但不是在它的开始,因为要达到合适的定位。 - 注完]



Answer 3:

这并不总是安全的这样做。 如果类有virtual方法,它最绝对不是。 数据成员保证出现在相同的顺序相同的访问级别块,但这些团体可以重新排序。

为了与这些类型转换的安全,你应该提供一个转换构造函数或转换运算符,而不是依赖于实现细节。



Answer 4:

典型地,在一个C结构成员都存储在他们声明的顺序。 然而元素必须正确对齐。 维基百科有一个很好的例子是如何工作的 。

我再次重申这里:

如果你有以下结构

struct MixedData
{
    char Data1;
    short Data2;
    int Data3;
    char Data4;
};

填充将不同数据类型之间,以保证正确的字节对齐插入英寸 char s的1字节对齐, short s为2字节对齐, int s为4字节对齐,等等。

从而,使Data2 2字节对齐,会有之间插入的1个字节的填充Data1Data2

还值得一提的还有,可以改变包装排列机制。 见的#pragma包 。



文章来源: Order of storage inside a structure / object