指针和引用

引用:就是给已经存在的变量起一个别名

定义的格式:类型&引用变量名 = 已定义过的变量名。
引用的特点:1、一个变量可以取多个别名 2、引用必须初始化 3、引用只能在初始化的时候引用一次,不能改变为再引用其他的变量(从一而终)

可以引用一个引用的变量(别名的别名):

int& b = a;        int &c = b;

const引用:

int d1 = 4;
    const int&d2 = d1;
    d1 = 5;//d1 改变可以改变d2的值
    //d2 = 6;不能,因为d2是const类型
    const int d3 = 7;
    int&d4 = d3;//这样是不可以的
    const int&d5 = d3;
    //常引用可以引用非常量,非常引用不能引用常量,

这就跟const是很像的,不能将范围扩大化,一个常引用是可以作为一个普通变量的别名的,但是一个非常引用是无法做为一个const类型变量的别名的。

引用作为参数:

  • 值传递:如果形参为非引用的传值方式,怎会生成临时的局部变量来接收实参的值
  • 引用传递:如果形参为引用,类型,则形参是实参的别名,那么将不会再生成临时变量。这就很大的节省了空间。特别是当参数是一个很大的结构体的时候,这就会节省很大的空间。
  • 指针传递,这虽然和引用很像,但是还是引用效率更好点,因为,指针还是要开辟空间的,但是引用就只是形参的额别名,不需要开辟空间。
  • 注意:当在函数内部我们不需要去改变形参的数值的时候,传参尽量使用常引用,这也回赠加代码的安全性
  • 传值作为返回值&引用作为返回值

通过汇编看函数的调用栈帧

int Add (int a, int b)
{
    return a + b;
}
void Test ()
{
    int ret = Add(1, 2);
}
int main ()
{
    Test();
    return 0;
}

这里写图片描述
当传引用的时候
这里写图片描述
传值返回时,是将ret放在eax寄存器中
传引用返回时,是取ret的地址放到eax寄存器中。

所以不要返回一个临时变量的引用,这会导致,出现野指针的现象,内存泄漏。
那我们该如何判断到底是返回值还是返回引用呢?
如果一个对象出了作用域还存在,那么就返回一个引用,如果一个对象出了作用域就不存在了,那就返回引用。

引用和指针的区别:

  • 引用必须先初始化,而且只能初始化一次,之后就不能再改变;而指针变量的值
  • 引用必须指向有效的变量,指针可以为空。
  • sizeof指针和引用不一样,指针是对象地址的大小,而引用则是引用的这个对象的大小。
  • 指针和引用自增自减不同,指针是指向下一个位置,而引用则是对象加1
  • 相对而言:引用比指针更加安全。
  • 在底层实现上其实指针和引用是一样的。
    这里写图片描述
    可以从汇编看出来:底层原理是相同的,引用就是指针。
    先保存到一个寄存器,然后让这个指针(引用)指向这个寄存器
posted @ 2018-04-03 12:17  chan0311  阅读(166)  评论(0编辑  收藏  举报