美文网首页
对象直接访问与指针访问

对象直接访问与指针访问

作者: wangwhatlh | 来源:发表于2021-11-06 11:59 被阅读0次

代码

class Person{
    public:
        int id;
        int age;
        int height;
        void display(){
            cout<<this<<"   id = "<<id<<",age = "<<age<<",height = "<<height<<endl;
        }
};
int main(int argc, const char * argv[]) {
    Person person;
    person.id = 10;
    person.age = 20;
    person.height = 30;
    person.display();
    
    // 指针访问 1
    Person *p1 = (Person *)&person;
    p1->age = 40;
    p1->height = 50;
    p1->display();
    // 指针访问 2
    Person *p2 = (Person *)&person.id;
    p2->age = 40;
    p2->height = 50;
    p2->display();
    // 指针访问 3
    Person *p3 = (Person *)&person.age;
    p3->age = 40;
    p3->height = 50;
    p3->display();
    return 0;
}

打印如下
0x7ffeefbff430 id = 10,age = 20,height = 30
0x7ffeefbff430 id = 10,age = 40,height = 50
0x7ffeefbff430 id = 10,age = 40,height = 50
0x7ffeefbff434 id = 40,age = 40,height = 50
可以看出第四个打印不一样,细思一下,大致可以猜到是因为person对象与其第一个成员id地址都是一样,正如打印0x7ffeefbff430,而第四个是0x7ffeefbff434是指向第二个成员age,正好后4个字节。但还是有疑问滴,明明没改id,为啥变呢,那就探究下其汇编代码了,在这之前先简单了解下指令相关:
/**
*%rax 通常用于存储函数调用的返回结果,同时也用于乘法和除法指令中。
%rsp 是堆栈指针寄存器,通常会指向栈顶位置
%rbp 是栈帧指针寄存器,用于标识当前栈帧的起始位置
%rdi,%rsi,%rdx,%rcx,%r8,%r9 用来传递函数参数,依次对应第1参数,第2参数至第6参数
%rbx,%r12,%r13,%14,%15 ,%r10,%r11 用作数据存储,属于通用性更为广泛的寄存器,编译器或汇编程序可以根据需要存储任何数据。
*/
对象访问:

    0x1000030b6 <+22>:  movl   $0xa, -0x20(%rbp) // 将10赋给该地址所在内存值,可以判断该地址是id成员的地址
    0x1000030bd <+29>:  movl   $0x14, -0x1c(%rbp) // person.age = 20;
    0x1000030c4 <+36>:  movl   $0x1e, -0x18(%rbp) // person.height = 30;
    0x1000030cb <+43>:  leaq   -0x20(%rbp), %rdi // 
    0x1000030cf <+47>:  callq  0x100003160     //     person.display();

很明显,只是直接赋值方式
P1:

/**
    Person *p1 = (Person *)&person;
    p1->age = 40;
    p1->height = 50;
    p1->display();
*/
    0x1000030d4 <+52>:  leaq   -0x20(%rbp), %rax // 将-0x20(%rbp)的地址拷贝到rax中,这里应该是person 的地址,p1指针的数据
    0x1000030d8 <+56>:  movq   %rax, -0x28(%rbp) // 
    0x1000030dc <+60>:  movq   -0x28(%rbp), %rax  // -0x28(%rbp)赋给rax
    0x1000030e0 <+64>:  movl   $0x28, 0x4(%rax)  // rax下4字节的数据存储40,age
    0x1000030e7 <+71>:  movq   -0x28(%rbp), %rax 
    0x1000030eb <+75>:  movl   $0x32, 0x8(%rax) // 将50赋给0x8(%rax) ,第8字节后数据height
    0x1000030f2 <+82>:  movq   -0x28(%rbp), %rdi    
    0x1000030f6 <+86>:  callq  0x100003160

可以看出底层是通过指针地址偏移指向来修改成员变量的
P2:

    0x1000030fb <+91>:  leaq   -0x20(%rbp), %rax
    0x1000030ff <+95>:  movq   %rax, -0x30(%rbp) // 
    0x100003103 <+99>:  movq   -0x30(%rbp), %rax
    0x100003107 <+103>: movl   $0x28, 0x4(%rax)
    0x10000310e <+110>: movq   -0x30(%rbp), %rax
    0x100003112 <+114>: movl   $0x32, 0x8(%rax)
    0x100003119 <+121>: movq   -0x30(%rbp), %rdi
    0x10000311d <+125>: callq  0x100003160   

P3:

    0x100003122 <+130>: leaq   -0x20(%rbp), %rax
    0x100003126 <+134>: addq   $0x4, %rax // 递增%rdx 4字节
    0x10000312c <+140>: movq   %rax, -0x38(%rbp)
    0x100003130 <+144>: movq   -0x38(%rbp), %rax
    0x100003134 <+148>: movl   $0x28, 0x4(%rax)
    0x10000313b <+155>: movq   -0x38(%rbp), %rax
    0x10000313f <+159>: movl   $0x32, 0x8(%rax)
    0x100003146 <+166>: movq   -0x38(%rbp), %rdi
    0x10000314a <+170>: callq  0x100003160 

p3指向了原person.age,也就意味着其首成员p3->id是原person.age的值,这就是解释了为啥p3->id为40。
同样值得注意的是person.display())与p3->display()结果又不一样,因为两者地址已经不一样

相关文章

  • 对象直接访问与指针访问

    代码 打印如下0x7ffeefbff430 id = 10,age = 20,height = 300x7ff...

  • 9.指针与数组的区别

    访问指针时,先要找到指针变量本身的地址,从该地址再取到存放的指针值,然后对指针指向的对象进行访问,是间接访问。访问...

  • 对象名不会被看作对象的地址

    类对象访问类成员一是通过对象名.访问,二是通过对象指针->访问,若是对象名可被看做对象的地址,那对象名.访问和对象...

  • 1.2.09_C++ 指向类的指针

    C++ 类 & 对象 一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算...

  • 对象的实例化

    创建对象的方式 对象创建的过程 对象的内存布局 对象的访问定位 hotspot使用直接指针 其他的方式:句柄

  • 多态

    (2)通过指针访问对象成员函数

  • 15章:内存与对象

    对象与内存 15.1指针和指针的值 对象只能通过指针访问,所以人们常用指向对象的指针来称呼该对象,例如有时候说“n...

  • 2017.9.14

    对象数组,指针,内存访问方式通过变量名地址访问,地址运算符,&、指针变量 概念,动态存储分配

  • 特殊数据类型

    指针 GO 语言像 C 一样有指针,可以通过指针访问数据,但是 GO 的指针要安全的多: 首先,访问空指针会直接报...

  • Effective Objective-C 2.0读书笔记(三)

    5.在对象内部尽量直接访问实例变量 1."通过属性访问"与"直接访问"实例变量的区别 由于不经过Objective...

网友评论

      本文标题:对象直接访问与指针访问

      本文链接:https://www.haomeiwen.com/subject/opqjzltx.html