C++ 成员变量的内存分配

静态成员不占用对象空间;
成员函数不占用对象空间;
构造函数不占用对象空间;
析构函数不占用对象空间;
虚函数不直接占用对象空间;
如果类的成员中含有虚函数,那么会在对象内存的开始位置添加一个指向虚函数表的指针;
该虚函数表的大小与虚函数的数量无关;
虚函数无论被继承多少次,依旧是虚函数;
如果该类是由其他类派生而来,那么该类对象的大小除要包含该类所有成员变量大小外,还应包含基类的成员变量大小;
如果基类包含虚函数,那么派生出来的类对象也应该包含一个虚函数表指针;
所有内存占用应遵循内存对其的原则;

先看下面代码:

C/C++ code
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<iostream>
using  namespace  std;
 
class  A
{
private :
int  b;
public :
int  c;
void  outthis()
{
cout<< "对象本身的地址:" << this <<endl;
}
void  outa()
{
cout<< "成员变量a的地址:" <<& this ->a<<endl;
}
void  outb()
{
cout<< "成员变量b的地址:" <<& this ->b<<endl;
}
void  outc()
{
cout<< "成员变量c的地址:" <<& this ->c<<endl;
}
 
private :
int  a;
};
int  main()
{
A s;
s.outthis();
s.outa();
s.outb();
s.outc();
system ( "pause" );
return  0;
}


运行结果如下:
[img=http://b97.photo.store.qq.com/psb?/2fb002c1-853a-4e26-9859-d79af27c9684/B2jOZUWjjqr.Ak2uVl76fQRB6qooUUwRzHWcZEJ2x60!/b/Yfa82zlFcAAAYtMm1zm2cAAA][/img]

这里可以看到,普通数据成员的内存分配顺序,是按照声明变量的顺序来排序的,跟共有私有无关;

[img=http://b99.photo.store.qq.com/psb?/2fb002c1-853a-4e26-9859-d79af27c9684/U1fipFp4ZxGz6KC71C.rql*tdQxD1h2z8w3NsVEyBK4!/b/YSVOCDvBbwAAYljMBjs8bgAA][/img]
 当我们试图在类外访问对象的私有数据时,会提示无法访问;
有没有一种方法绕过这种限制呢?
[img=http://b100.photo.store.qq.com/psb?/2fb002c1-853a-4e26-9859-d79af27c9684/NEBcJHAGOPGQ.bW2vIcJ0zM6st.2*rbL3ngLYWj2npE!/b/YYYysDsLVAAAYsTpoDuFUwAA][/img]
这里我们看到可以通过一些其他手段访问私有数据;
有人问了 如果有多个私有数据怎么访问?
综合上面的知识,把代码做了如下修改,再看结果:
[img=http://b102.photo.store.qq.com/psb?/2fb002c1-853a-4e26-9859-d79af27c9684/7n4dmQalAUDq1Zztjy8KYh1dBVaKl2ES*Y3pBZiJiIE!/b/YTWm0zz.JwAAYle22Ty5JwAA][/img]
 可以看到,我们通过其他手段还是能够绕过私有数据的权限进行访问的;
详解一下:
声明变量s后,调用构造函数给s的三个成员a,b,c变量赋值55,66,77;
这时s内部的结构为:
[img=http://b104.photo.store.qq.com/psb?/2fb002c1-853a-4e26-9859-d79af27c9684/0yIfQTSbYJuB8Xkc1f2UuSTMhsG4fLvWH3PrxvvcoRw!/b/YW9OAz5MJwAAYjnXBz4uJwAA][/img]
我们前面证明了,在没有其他情况的前提下(比如虚函数需要在开始位置添加一个指向虚函数表的指针);
s的地址就是第一个成员的地址;
所以 &s就是变量c的地址;但是这个地址的类型为A*;我们还要把它转化为int*型,才可以对其进行正常读取;
所以得到*(int*)&s;
然后再看a;
先要得到他的地址; a的地址相对于后移了sizeof(int)个字节;
(char*)&s+sizeof(int)这样就得到他的地址了;
然后跟c一样转换类型再取值,就象这样:*(int*)((char*)&s+sizeof(int))
有人要问:为什么先把&s转化为char*类型?
看下面例子:
int a;
int*p=&a;
假设此时p值为0x00000010
那么p+1呢?是0x00000011吗?
不是的;应该是0x00000014;
p+1相当于p+sizeof(int);
也就是他的一个的偏移量是他所存放的数据类型的内存占用量;
所以我们先临时从A*类型转换为char*类型,让&s+sizeof(int)时表示内存地址+sizeof(char)*sizeof(int);而不是+sizeof(A)*sizeof(int);
然后b的取值方法就类似了,只不过他是便宜两个int的大小而已;
好了就这点东西吧.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值