最近我在做一个项目的时候遇到了这个问题,这让我有点困惑。因此,我决定编写一个测试程序,以得到一个明确的答案:
#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;
}这个程序创建了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这三个对象怎么能在内存中共享相同的位置呢?如果我缩放这个程序到有50个层(对象)呢?还是一万?我不太确定这怎么可能。有人能帮我解释一下这是怎么回事吗?
编辑:,可能是因为我实例化了对象,而不是对象的构造函数?我不知道。
发布于 2013-01-23 13:47:39
最明确的答案是C++标准给出的答案:
两个不是位字段的对象可能具有相同的地址,如果其中一个是另一个的子对象,或者至少一个是大小为零且类型不同的基类子对象;否则,它们将具有不同的地址。
也就是说,如果一个对象是另一个对象的主题,它们可能具有相同的地址。
在C++11中,标准布局结构(尽管其名称也可以是class )对象的第一个成员的地址与对象本身具有相同的地址:
指向使用
reinterpret_cast适当转换的标准布局结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。
由于您的类都是标准布局,所以您所观察到的行为由C++11保证。
在C++03中,规则类似,但适用于POD-struct类型,而不是标准布局结构类型。但是,您的类不是POD-struct类型,因为它们有用户定义的析构函数.所以你在这里看到的行为不是由C++03保证的。
那么为什么会发生这种情况呢?好吧,一个类实际上是一种将一些数据组合在一起并提供对这些数据的操作的方法。考虑一个只包含int的类,如下所示:
class A
{
int x;
};这个类是由int组成的。当您创建一个A类型的对象时,您真正要做的就是为它的内部分配足够的空间并初始化它们(或者在本例中,不是初始化它们)。假设我们创建了两个A实例
A a1;
A a2;我们记忆中有什么?你可以想象它看起来是这样的:
a1 a2
┌──────┬──────┐┄┄
│ A │ A │
└──────┴──────┘┄┄
Memory ------->如果我们知道A只包含一个int --也就是说,一个A对象实际上不过是一个int (除了一些填充物)--那么,如果我们对它进行更多的分解,我们就知道内存实际上是这样的:
a1 a2
┌──────┬──────┐┄┄
│ int │ int │
└──────┴──────┘┄┄
Memory ------->您可以在这里看到,A和int都有相同的地址,因为int是A类型对象的子对象。如果A同时包含一个int和一个char,它可能如下所示:
a1 a2
┌──────┬──────┬──────┬──────┐┄┄
│ int │ char │ int │ char │
└──────┴──────┴──────┴──────┘┄┄
Memory ------->我们知道char的地址将比int高,因为标准又一次这样说:
分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便以后的成员在类对象中具有更高的地址。
注意,子对象不一定与包含在其中的对象共享其地址,即使它是第一个。这完全取决于编译器。
发布于 2013-01-23 13:47:48
在内存中,类的实例(通常)占用其数据成员的空间(加上虚拟表指针或其他实现定义的位)。
从纯数据成员的角度来看,layer1实例只包含layer2的一个实例,因此存储在layer1中的第一个元素(与layer1实例本身具有相同地址的元素)自然是layer2实例。同样的推理也适用于layer2和layer3。
发布于 2013-01-23 13:46:59
我从你的观察中没有发现任何奇怪的东西。对象由内存中一个又一个写入的成员组成,因此对象的地址和其第一个成员的地址是相同的。无论你有多少层都是这样。
https://stackoverflow.com/questions/14481180
复制相似问题