对象和内存

目录

类的定义

demo

对象调用成员函数汇编解释

内存空间

对象的内存的排布顺序

demo

成员变量内存排布分析

对象直接访问成员变量

通过指针间接访问所指向对象的成员变量

 一个p->dispaly() 的demo


类的定义

demo

#include <iostream>
using namespace std;

class Persion
{

public:
    int m_age;
    //void run(Persion *persion){
    //    //显示调用
    //    cout << persion->m_age << " run()" <<endl;
    //}
    void run(){
        //this 存储函数调用者的地址,例如 this 存储 &persion 或 this 存储 &persion1
        cout << this->m_age << " run()" <<endl;
    }
};
void test(){
    Persion persion;   //persion对象占用4个字节:因为只有一个int类型(4个字节)的成员变量
    persion.run();     //在编译过程中,将为函数分配一个内存地址,此次调用将编译成 call 函数地址。 如call 0086141A

    Persion persion1;  //persion1对象占用4个字节:因为只有一个int类型(4个字节)的成员变量
    persion.m_age = 20; 
    persion.run();     //call函数地址 如call 0086141A

    Persion *p = & persion; // 64位,p占用8个字节
    p->m_age = 30;
    p->run();
    cout << "sizeof(persion) = " << sizeof(persion) <<endl;
    cout << "sizeof(p) = " << sizeof(p) <<endl;
    /*
    persion对象和指针p的内存都在函数的栈空间,自动分配和回收
    */
}
int main(){
    test();
    return 0;
}

对象调用成员函数汇编解释

普通函数调用对应的汇编是call xxxxx地址


persion1.run();对应的汇编:
lea       ecx,[ebp-0Ch] /取地址,其中 ebp-0Ch是persion1对象的地址,ecx存储者persion1的地址
call      00061366

下面是persion1.run()调用run()过程和生成的汇编:
void run(){
    this->m_age = 3;
}
/*
mov        dword ptr [ebp-8],ecx   //persion1的对象的地址值放到了this指针所在的存储空间,其中ecx存放的是persion1的地址,ebp-8:this指针的地址
mov        eax,dword ptr [ebp-8] //取出this指针里面存储的地址值放到eax,执行完后,eax里放的是persion1的地址值
mov        dword ptr [eax],3 // 把3放到了persion1的存储空间
*/

内存空间

代码区用于存放代码上面代码块中run()内存在代码区
栈空间     

1. 每调用一个函数就会给它分配一段连续的栈空间,等函数调用完毕后会自动回收这个栈空间

2.自动分配和释放

persion, persion1 以及和对应的成员在栈空间
堆空间需要主动申请和释放
数据段(全局区)用于存放全局变量等

对象的内存的排布顺序

对象的内存的排布顺序按照成员变量定义的顺序

demo

/*
对象的内存的排布顺序按照成员变量定义的顺序
*/
#include <iostream>
using namespace std;

class Persion
{
public:
    int m_id;
    int m_age;
    int m_height;

    void display(){
        cout  << "id:"  <<m_id << "age:" << m_age << "height:" << m_height<<endl;
    }
};
int main(){
    //此 persion 对象是在栈空间
    Persion persion;
    persion.m_id = 10;
    persion.m_height = 30;
    persion.m_age = 20;
    cout  << "&persion: " << &persion <<endl;
    cout  << "&persion.m_id: "  << &persion.m_id <<endl;
    cout  << "&persion.m_age: "  << &persion.m_age <<endl;
    cout  << "&persion.m_height:"  << &persion.m_height <<endl;
    return 0 ;
}


>>结果
&persion: 0x61fe14
&persion.m_id: 0x61fe14
&persion.m_age: 0x61fe18
&persion.m_height:0x61fe1c

成员变量内存排布分析

内存地址内存数据
&persion&persion.m_id0X00E68B6010
0X00E68B61
0X00E68B62
0X00E68B63
&persion.m_age0X00E68B6420
0X00E68B65
0X00E68B66
0X00E68B67
&persion.m_height0X00E68B6830
0X00E68B69
0X00E68B6A
0X00E68B6B

对象直接访问成员变量

Persion persion;
persion.m_id = 10;
persion.m_height = 30;
persion.m_age = 20;

生成的汇编是:
mov             dword ptr [ebp-14h],0Ah //ebp-14h是persion对象的地址值
mov             dword ptr [ebp-10h],14h  // ebp-10h - ebp-14h = 4个字节 
mov             dword ptr [ebp-0Ch],1Eh

通过指针间接访问所指向对象的成员变量

1、从指针中取出对象的地址

2、利用对象的地址+成员变量的偏移量计算成员变量的地址

3、根据成员变量的地址访问成员变量的存储空间

Persion *p = & persion;
p->m_id = 10;
p->m_height = 10;
p->m_age = 10;
p->display()

//Persion *p = & persion;
lea             eax,[ebp-14h]                //将persion对象的地址取出赋值给eax,ebp-14h是persion对象的地址,
mov             dword ptr [ebp-20h],eax       //ebp-20h是指针p的地址


//exa存储的是persion对象的地址,也就是persion.m_id的地址
// p->m_id = 10;
mov             eax, dword ptr [ebp-20h]      //取出指针变量p存储的内容取出放入persion对象地址
mov             dword ptr [eax],0Ah           //将10放入persion对象的存储空间。
注释:[]里放的是地址,[eax]中eax是地址值,dword ptr [ebp-20h] 从某个存储空间取出一个地址值说明是个指针的存储空间,可以推出ebp-20h是个指针的地址值,[ebp-20h]是指针,dword ptr [ebp-20h]是指针存储的值
mov             eax, dword ptr [ebp-20h]
mov             dword ptr [eax+4],0Ah         // eax+4就是第二个成员变量的地址值

mov             eax, dword ptr [ebp-20h]
mov             dword ptr [eax+8],0Ah

mov             eax, dword ptr [ebp-20h]
call            003B141F

 一个p->dispaly() 的demo

class Persion
{
public:
    int m_id;
    int m_age;
    int m_height;

    void display(){
        cout  << "id:"  <<m_id << "age:" << m_age << "height:" << m_height<<endl;
    }
};
int main(){
    Persion persion;
    persion.m_id = 10;
    persion.m_height = 30;
    persion.m_age = 20;
    persion.display();    //  id:10 age:20 height:30

    Persion *p = (Persion *) &persion.m_age;
    p->m_id = 40;
    p->m_age = 50;
    persion.display();    // id:10 age:40 height:50 因为将persion对象的地址传给display函数的this

    p->display();// id:40 age:50 height:其他数据。因为将指针p里面存储的地址值传递给display函数的this
}

p->display(),p指向的是persion地址+4,即m_age的地址,那么在dispaly中的this->m_id,this->m_age,this->m_height,的偏移量自动加了4个字节,最终导致m_height的偏移量超过12.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值