指针和引用

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

原文地址:https://www.cnblogs.com/Joezzz/p/9942555.html