我最近在处理一个项目时遇到了这个问题,这让我有点困惑.所以我决定编写一个测试程序来获得明确的答案:
#include <iostream>
using namespace std;
class layer3{
public:
layer3(){}
~layer3(){}
private:
};
class layer2{
public:
layer2(){}
~layer2(){}
layer3* GetBAddress(){return &b;}
private:
layer3 b;
};
class layer1{
public:
layer1(){}
~layer1(){}
//returns the address of a, which is a 'layer2' object
layer2* GetaAddress(){return &a;}
//returns the address of b, which is is a layer 3 object
layer3* GetDeepBAddress(){return a.GetBAddress();}
private:
layer2 a;
};
int main(){
layer1 t;
cout << &t << " : layer 1's address" << endl;
cout << t.GetaAddress() << " : layer 2's address" <<endl;
cout << t.GetDeepTLAddress() << " : layer 3's address" <<endl;
}
Run Code Online (Sandbox Code Playgroud)
该程序创建3个对象.layer2在layer1中创建,layer3在layer2中创建.然后我调用获取layer1,layer2和layer3的地址,就像之前发生的那样,这是输出:
$ ./a.exe
0x28ac4f : layer 1's address
0x28ac4f : layer 2's address
0x28ac4f : layer 3's address
Run Code Online (Sandbox Code Playgroud)
这三个对象如何在内存中共享相同的位置?如果我将此程序缩放为50层(对象)怎么办?还是10,000?我不太确定这是怎么回事.有人可以把我放在我的位置并解释这里发生了什么?
编辑:也许是因为我在私有而不是在对象的构造函数中实例化对象?巴哈,我不知道.
Jos*_*eld 12
最明确的答案是C++标准给出的:
如果一个是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们是不同类型的,则不是位字段的两个对象可以具有相同的地址; 否则,他们应有不同的地址.
也就是说,如果一个对象是另一个对象的主题,它们可能具有相同的地址.
在C++ 11中,标准布局结构(尽管它的名称,也可以是class)对象的第一个成员保证与对象本身具有相同的地址:
指向标准布局结构对象的指针(适当地使用a转换)
reinterpret_cast指向其初始成员(或者如果该成员是位字段,则指向它所驻留的单元),反之亦然.
由于您的类都是标准布局,因此C++ 11保证您观察到的行为.
在C++ 03中,规则类似,但适用于POD结构类型,而不是标准布局结构类型.但是,您的类不是POD结构类型,因为它们具有用户定义的析构函数.因此,C++ 03 无法保证您在此处看到的行为.
那为什么会发生这种情况?实际上,所有类都是将一些数据组合在一起并提供对该数据的操作的方法.考虑一个只包含int类似的类:
class A
{
int x;
};
Run Code Online (Sandbox Code Playgroud)
所有这一课都是由这个组成的int.当你创建一个类型的对象时A,你所做的只是为它的内部分配足够的空间并初始化它们(或者在这种情况下,不是初始化它们).假设我们创建两个实例A:
A a1;
A a2;
Run Code Online (Sandbox Code Playgroud)
我们在记忆中有什么?你可以想象它看起来像这样:
a1 a2
?????????????????
? A ? A ?
?????????????????
Memory ------->
Run Code Online (Sandbox Code Playgroud)
如果我们知道A只包含一个int- 也就是说,一个A对象实际上只是一个int(除了可能是一些填充) - 那么我们知道如果我们将它分解得更多,那么内存实际上看起来像这样:
a1 a2
?????????????????
? int ? int ?
?????????????????
Memory ------->
Run Code Online (Sandbox Code Playgroud)
你可以在这里看到,A并且int都将具有相同的地址,因为它int是类型对象的子对象A.如果A包含a int和a char,它可能看起来像这样:
a1 a2
???????????????????????????????
? int ? char ? int ? char ?
???????????????????????????????
Memory ------->
Run Code Online (Sandbox Code Playgroud)
我们知道char会有比地址更高的地址int,标准也是这样说的:
分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.
请注意,子对象不一定与其包含的对象共享其地址,即使它是第一个.这完全取决于编译器.