我一直在阅读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_(作为私有)的声明顺序是未指定的。
答案 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_
内存中的(相对)布局未指定。这与初始化顺序无关。