c/c++区别(二)引用

 第6个区别:引用 

 一.引用传入

变量:内存单元的别名

引用:内存单元的别名

 

引用是一个别名

底层处理:C++中和指针处理相同 在用到引用变量的地方 系统会自动解引用 引用开辟内存

 

引用的特点

  1. 必须要初始化
  2. 引用初始化的变量一定要可以取地址
  3. 引用是不可改变的
  4. 引用只能访问引用变量所引用的内存单元

二.1.const和一级指针引用的结合

Const只是为了杜绝间接访问修改常量内存块的风险

扫描二维码关注公众号,回复: 4178032 查看本文章

间接访问:

2.const和二级指针的结合

Eg:  (1) const int a = 10;          修改后         const int a = 10;

      Int* p = &a;              ---------->         const int* p =&a;

      Int** q= &p;                              const int**q = &p;

 

      此时const修饰a,const修饰谁 谁就是直接访问 直接访问:a 间接访问:*p ,**q

只看间接访问 这两个前面都没有加修饰 于是都加上const 杜绝修改常量内存块的风险 成为const*p ,const**q

(2)int a = 10;                   修改后         int a = 10;

Const int* p = &a;           -------------->       const int*p = &a;

Int **q=&p                                 const int**q=&p;

 

   此时const修饰*p,直接访问:a,(*p就是a),间接访问:*P,**q(从const修饰的那一行看起 因为const之前的都是普通变量 没有问题)

   只看间接访问 此时*p加了修饰 而**没有加 加上const即可

(3)int a = 10;                  修改后          int a = 10;

Int* const p = &a;           -------------->       int* const p =&a;

Int**q = &p;                                int * const*q =&p;

 

    此时const修饰p 直接访问:p 间接访问(比直接访问大一级或几级的):*q 此时*q没有被修饰 有修饰常量内存块的风险 加上const即可杜绝

(4)特例!切记

Int a = 10;                  修改后          int a = 10;

Int*p = &a;               ---------------->       const int * p =&a;//方法二

Const int**q =&p; //int**==>const int** 错误    const int* const*q = &p;//方法一

 

此时const修饰**q 直接访问:a 间接访问:从const起才看间接访问 :**q 按理来说const 修饰了**q 应该没问题 但这个代码是错误的,其中**q还隐藏包含了*q这个间接访问,首先来看这么一行代码

 

 

此时有两种解决办法

  1. 让普通指针无法指向常量内存块 也就是在*q前加const  此时变为const *q *q就是p 则此时*q不能保存a的地址 无法指向a 那么就更无法修改了
  2. 普通指针可以指向 但不能修改 此时变为const int* p 此时a不会修改了

因此不允许int**==>const int**(特例)虽说是权限缩小 但是是错误的

 

(5)int a = 10;

Int* p =&a;

Int* const *q =&p;

 

此时const修饰*q 直接访问:p 间接访问:*q 有const修饰 所以正确

(6)Int a = 10;

Int*p =&a;

Int** const q= &p;

 

此时const修饰q 直接访问:q 间接访问:无 间接访问都没有了 因此没有修改常量内存块的风险

 

4.const和引用的结合

常引用:Int &c =20;//错误 引用底层是指针 无法取常量内存块 无法取地址

Const int&c =20(立即数 ,常量);

常引用可以引用立即数 立即数放到临时量中 临时量在内存上 常引用来引用临时量

 

Int a = 10;

Const int&b = a;//const int == int 正确

引用不参与类型(忽略&) 指针参与类型

左操作数的权限<=右操作数的权限  特别要注意const int*<= int*

 

(1)Int a = 10;

Const int* p =&a;

Const Int* &q = p;//int*  const int* 错误 左操作数权限大 所以在前面加const

 

(2)int a = 10;

        Int* const p =&a;

        Int* const&q = p;//int* int*const 错误 左操作数权限大

(3)特例:

Int a = 10;

        Const Int*p = &a;

        Const int*const &q = p;//const int*  int*按理来说是正确 实际上错误 还有隐藏的q有修改常量内存块的风险 和上面的特例一样

 

5.引用和形参

形参加上const的作用:

(1)防止实参被修改

(2)引用立即数

 

引用作形参和普通变量作形参的区别:

(1)引用修改实参的值

(2)引用不能引用立即数 部分实参无法调用

 

6.引用 指针 和返回值的结合

不能返回局部变量的地址或引用

有可能被调用函数清栈时有新的函数调用 此时main函数里还保存以前函数的地址 地址一直保留 根据地址会访问  此时在调用新函数 新函数的值就会覆盖以前的函数的值 此时根据地址访问到的就是新的值 以前的值已经被覆盖 所以会出错

 

7.引用 指针来接收返回值时的使用

 

(1)

int func()

{

  Int tmp = 0;

  Return  tmp;

}

 

Int main()

{

  Int irt = func() //正确func的返回值为4个字节 由寄存器带出

  Int *prt = &func() // 错误 func由寄存器带出值 寄存器不能取地址

  Const Int& rrt = func() //此时寄存器里为常量 加上const变为常引用才正确

}

 

(2)

Int* func()

{

Static Int tmp = 10;//.data

Return &tmp;

}

返回值为int* 4字节 凡是4字节都由寄存器带出 此时寄存器中存的是tmp的地址

Int main()

{

  Int irt = *func() //Int irt = *eax eax放的是地址 地址可以解引用 实际为Int irt = tmp 正确

  Int* prt = func()//int* = eax;正确

  Int& rrt = *func()//int& rrt = *eax eax放的是tmp的地址 在解引用就是tmp rrt引用tmp可以

Int* const & prrt = func()//int* & prrt = eax 引用的变量要能取地址 eax无法取地址 所以加上const变为常引用即可

}

 

(3)

Int& func()

{

  Int tmp = 0;

  Return  tmp;

}

引用底层是指针 返回的是tmp的地址 而且针对func() 系统都有自动解引用

Int main()

{

   Int irt = func()//正确int irt= eax eax(&tmp) *eax 就是tmp

   Int& rrt = func()//eax(&tmp)==>*eax(tmp)==>tmp 可以引用一个普通的变量tmp

   Int* prt = &func()//eax(&tmp)==>*eax(tmp)==>tmp==>&tmp 可以取tmp的地址 可以指向一个能取地址的变量

}

 

猜你喜欢

转载自blog.csdn.net/xiaobaibai915/article/details/84317780