非结构对象布局

时间:2016-12-06 09:19:04

标签: c++

我一直在阅读Lippman的“Inside the C ++ Object Model”我遇到了以下事情:

  

单个访问部分中的数据成员在C ++中保证按其声明的顺序排列。但是,多个访问部分中包含的数据布局未定义。

这是否意味着下面代码中的评论是正确的?

class Foo
{
public:
     Foo(): a_(1), b_(2), c_(3)
     {
          // it does not matter that the order of a_, b_, c_ is the same in class definition and in initialization list, we do not know which one will be initialized first?
     }

public:
     int a_;

private:
     int b_;

protected:
     int c_;
};

如果这是真的,那么几个包含成员组的私人部分呢?

class Foo
{
public:
     Foo(): a_(1), b_(2)
     {
          // is initialization order guaranteed?
     }

private:
     int a_;

private:
     int b_;
};

另外,也许我可以在标准中阅读有关它的任何内容吗?

UPD

当我有:

class Foo
{
public:
     Foo(): a_(1), b_(2) {}
private:
     int a_;
     int b_;
};

我确定一切正常:a_在b_初始化之前初始化。

当我有:

class Foo
{
public:
     Foo(): a_(1), b_(2) {}
public:
     int a_;
private:
     int b_;
};

据我所知,我无法确定在初始化b_之前初始化a_。

为什么呢?因为,正如我们所知,初始化的顺序仅由声明的顺序决定。但是在上面的说法中,a_(作为公共)和b_(作为私有)的声明顺序是未指定的。

1 个答案:

答案 0 :(得分:1)

布局:

如您所引用的文字所述,布局取决于声明的顺序和访问控制。具有相同访问控制的所有成员都被分配,以便后面声明的成员在对象中具有更高的成员。未指定具有不同访问控制的成员的顺序。请注意,这允许根据声明顺序布置所有成员。

  

具有相同访问权限的(非联合)类的非静态数据成员   控制(第11条)被分配,以便后来的成员有更高的   类对象中的地址。非静态分配的顺序   未指定具有不同访问控制的数据成员(第11条)。

     

N4296§9.2/ 13

初始化

初始化按成员退出的顺序进行,成员初始化程序的顺序(构造函数的:之后的内容)无关紧要:

  

然后,按照它们的顺序初始化非静态数据成员   在类定义中声明(再次无论顺序如何   MEM-初始化)。

     

N4296§12.6.2/ 13.3

访问控制并不重要。

经验验证

#include <iostream>
using std::cout;
using std::endl;

struct A
{
    A()
    {
        cout << "A" << endl;
    }
};

struct B
{
    B()
    {
        cout << "B" << endl;
    }
};

struct X
{
    A a;
    B b;
    X() : b(), a() {}
};

int main() {
    X x;
    cout << "a @ " << &(x.a) << endl;
    cout << "b @ " << &(x.b) << endl;
    return 0;
}

将输出(live on ideone

A
B
some_address
some_address + 1

解决您的编辑问题:

class Foo
{
public:
     Foo(): a_(1), b_(2) {}
public:
     int a_;
private:
     int b_;
};
  

据我所知,我无法确定在初始化b_之前初始化a_。

是的,您可以确保在a_之前初始化b_。这是由标准保证的。

  

但是在上面的说法中,a_(作为公共)和b_(作为私人)的声明顺序是未指定的。

引用说明a_b_内存中的(相对)布局未指定。这与初始化顺序无关。