• 指针和引用


    1.复合类型

      复合类型是指基于其他类型定义的类型,指针和引用就是复合类型

    2.指针

    2.1概念

      指针是一种复合类型,它指向某个对象,它本身也是一个对象,指针的值是它指向对象的地址,同时指针也有它自己的地址

    void func(int* p)
    {
        int m_value = 1;
        p = &m_value;
    }
    
    int main()
    {
        int n = 2;
        int *pn = &n;
        cout << *pn << endl;
        func(pn);
        cout << *pn << endl;
    
        return 0;
    }

    2.2sizeof指针

      sizeof指针得到是指针本身的大小(字节数),sizeof引用得到的是所引用对象的大小

    2.3指针的大小

      指针大小是由CPU实际运行的寻址位数决定,与所指向的对象的类型无关,寻址位数为16位则为2字节,32位为4字节(通常情况下),64位为8字节

    2.4空指针

      不指向任何对象的指针,它的值为NULL

    2.5跟指针有关的操作符

    1)取地址符&

    2)解引用符*

    2.6指针的比较

      同类型的指针可以比较,不同类型的指针比较会报错

    3.引用

    3.1概念

      引用仅仅是给对象起了一个别名,实质上跟原来的对象是同一个东西;定义引用时,必须初始化

    3.2引用的底层实现

    int main()
    {
        int x=1;
        int &b=x;
        return 0;
    }
    //汇编语言:vs编译环境在调试模式下,右键鼠标菜单->反汇编
    9:       int x = 1;     //源代码 
    00401048   mov         dword ptr [ebp-4],1  //汇编代码  
    10:      int &b = x;    //源代码
    0040104F   lea         eax,[ebp-4]          //汇编代码
    00401052   mov         dword ptr [ebp-8],eax//汇编代码

      mov dword ptr [ebp-4],1   //把1赋值给ebp(栈底指针)-4的地址
      lea eax,[ebp-4]     //把ebp-4的地址赋值给寄存器eax
      mov dword ptr [ebp-8],eax   //把寄存器eax里的值赋值给ebp-8的这块地址
    上述三行代码的作用就是将1赋值给x,然后将x的地址赋值给了引用b,所以,在底层,引用存放的是被引用对象的地址
    而在内存中,它是这样的:

      所以有这么一种说法:引用的底层是通过类似指针的方式实现的

    3.3如何获得引用的地址和其真正的值

    int main()
    {
        int  a = 1;
        int&  b = a;
        cout << "a:address->" << &a << endl;
        cout << "b:address->" << &b << endl;
    
        getchar();
        return 0;
    }
    运行结果: 
    a:address->0031FD54 
    b:address->0031FD54

      引用b的地址和变量a的地址一样,这种方法不能得到引用b的地址

    int main()  
    {  
       int x = 1;  
       int y = 2;  
       int &b = x;  
       printf("&x=%x, &y=%x, &b=%x, b=%x
    ",&x,&y,&y-1,*(&y-1));  
       return 0;
     }  
    运行结果: 
    &x=12ff7c, &y=12ff78, &b=12ff74, b=12ff7c

      引用b的地址可以间接通过&y-1来得到b的地址;*(&y-1) 就是b的值,从结果可以知道,b的值即x的地址,从而可以知道,从底层实现来看,引用的确存放的是被引用对象的地址,只不过,这些对于高级程序员来说是透明的,编译器屏蔽了这些细节

    4.函数的值传递、指针传递、引用传递

    1)值传递:发生拷贝,形参是实参的拷贝,改变形参的值并不会影响实参的值

    2)指针传参时,函数会创建一个副本指针(局部变量),这个副本指针的值和实参的值相同,副本指针的地址和实参的地址不同,函数可以通过副本指针对实参指针所指向的对象进行操作

    3)引用传参时,从底层看,形参其实也是作为局部变量在栈中开辟了空间,这个局部变量真实存放的其实是实参的地址(可从汇编层看到),在函数体内任何对形参的操作都会通过间接寻址的方式(即通过这个存放的地址去访问主函数中的实参)影响到主函数的实参;但是编译器隐藏了这些细节,通过编译器查看,形参和实参的地址相同,形参和实参的值也相同

       

    4)效率上讲,指针传递和引用传递比值传递效率高,编程过程中想要传递大的类对象时,值传递由于要拷贝整个对象将耗费更多的时间和空间

    参考资料

    https://blog.csdn.net/lws123253/article/details/80353197

  • 相关阅读:
    Redis 常用命令整理
    TCP系列01—概述及协议头格式
    TCP/IP详解--TCP网络传输数据包1460MSS和1448负载
    TCP中报文段大小(MSS)、MTU
    DNS 过滤脚本
    TCP SYN Cookies – DDoS defence
    python virtualenv venv 虚拟环境
    git 命令总结
    王兴三横四纵
    获取国税门户可供下载的资源文档
  • 原文地址:https://www.cnblogs.com/Joezzz/p/9942555.html
Copyright © 2020-2023  润新知