C++的引用 ‘&’

        引用这个操作在C语言中就已经存在了,它表示了一个取地址符,取地址符经常被用来在定义指针p的时候,在变量前面加上这个取地址符号,表示指针p指向了该变量的地址:

int* p = NULL;
int a = 0; 
p = &a;

        又或者是在函数的参数传递时候,形参定义的是指针,实参数变量的取地址,通过指针传递的形式来进行数据的交换操作:

void Test_PointerTransport(int* p, int* q){
  int temp;
  temp = *p;
  *p = *q;
  *q = temp;
}
​
​
int main(){
  int serven_1 = 1;
  int serven_2 = 2;
  Test_PointerTransport(&serven_1, &serven_2);        // 作用是交换连个数值
}

        但是在C++中,引用还有另外一个用途,它不仅仅只有上面的取地址运算符一种功能。下面小编就来剖析一下C++中引用的相关知识点,当你掌握了这些知识点,在以后的开发过程中,你会发现你的代码的执行效率和代码质量完全提升了一个档次。

什么是引用

        在C++中,引用就是将某个变量另取一个别名,像小时候我们村里面的老人都会给小孩子领取一个土名字一样(像小编的名字叫 “谢文”,有人给我起了一个“seven”),所以你叫我真名也行,叫我别名也是可以的,至少你在后面叫我,我还是会回头看你的~~~。

        好了,引用就是给变量起一个别名的意思,对引用的操作和对变量直接操作的效果是完全一样的。引用的声明方法是:

类型标识符&  引用名 = 变量名;

代码:

int serven_1;
int& serven_2 = serven_1;          // 给serven_1起一个别名叫做serven_2

在这里的符号&不是取址运算符,而是标识符,起到了标识的作用。

值得注意的一点是:

  • 在声明引用时,一定要对其进行初始化;

  • 声明了一个引用后,该引用不能再去重新引用别人了(这一点跟我们之前讲的指针常量一样,其实引用底层实现是指针常量);

  • 声明引用只是对变量进行取别名的操作,不是定义一个新的变量来引用,所以serven_2本身就不是一种数据类型,系统也不会给引用分配存储单元,所以对引用求地址,就是直接对目标变量求地址(&serven_2 == &serven_1);

  • 不能给数组建立引用,因为数组里面有很多个元素,都不知道你要引用哪个。

引用的原理

        你在代码中看到的引用语句是这样的:

  int serven_1;
  int& serven_2 = serven1;

        但是实际上,你的这两行代码等价于:

int serven_1;
int* const serven_2 = &serven_1;        // serven_2是一个指针常量,这个指针常量指向变量serven_2

        所以从上面的代码我们可以看到,引用的原理就是指针常量(在小编之前的一篇文章中有讲到指针常量、常量指针和常量指针常量之间的区别,你可以去看一看),一旦serven_2引用了serven_1这个变量,那么serven_2就不能在引用别的变量了,跟指针常量的做法是一样的,而且也允许通过引用去修改被引用目标变量的数值。

引用的几种引用场景

1. 引用作为函数参数

        有开发经验的小伙伴都知道函数的参数传递有三种,分别是:值传递、指针传递和引用传递;

引用传递的代码如下:

​
void Test_Swap(int& serven_2){
  serven_2 = 2;
}
​
void main(){
  int serven_1 = 1;
  Test_Swap(serven_1);
  cout<<serven_1<<endl;
}

2. 常引用

    常引用就是说该引用是一个常量,不能通过引用符号去修改被引用的变量的数值,常引用的声明方式:

const 类型标识符& 引用名=变量名;

代码:

int serven_1 = 1;
const int& serven_2 = &serven_1;      // 一定要赋初始值
//serven_2 = 2;          // 不允许这个操作,因为此时的引用serven_2已经是常量了

        常量引用相当于常量指针常量,常量指针常量是指:该指针本身就是一个常量,不能够修改指向别的变量或者常量,并且不能通过指针的形式去修改变量的数值。

        常引用的优点就是:安全性

        因为当你的形参设定为常引用的话,你在函数里面不可以通过引用对变量进行修改,这也有助于代码的安全性。

3. 引用作为返回值

        引用作为返回值是指你要调用的函数是一个引用函数。

类型标识符& 函数名(形参){}

int& Test_Area_Quote(){
  int serven_1 = 1;      // 局部变量,出了这个函数就会被销毁掉
  return serven_1;
}
​
int& Test_Static_Quote(){
  static int serven_2 = 2;  // 静态变量,出了这个函数变量还在,只是出了这个函数就不能使能该变量了
  return serven_2;
}
​
​
void Quote_Main(){
  //int& serven_3 = Test_Area_Quote();        // 不允许返回局部变量做引用,因为局部变量出了作用域就会被销毁了
  //cout<<"serven_3引用Test_Area_Quote函数后的返回引用值为:"<<serven_3<<endl<<endl;
​
  int& serven_4 = Test_Static_Quote();          // 允许返回静态变量做引用,因为静态变量在程序的整个生命周期都存在
  cout<<"serven_4引用Test_Static_Quote函数后的返回引用值为:"<<serven_4<<endl<<endl;
​
  Test_Static_Quote() = 1000;              // 因为此时serven_4引用了函数Test_Static_Quote,那么直接修改函数的返回引用值也是可行的
  cout<<"e函数后的返回引用值为:"<<serven_4<<endl<<endl;
​
}

        从代码可以看到,引用函数的返回值中,函数Test_Area_Quote返回的是局部变量,而在main函数中定义了一个引用来引用这个函数的返回值,这种操作是不允许的(偷偷告诉你在Windows操作系统中的VS是可以运行的,只是给了警告要求我们不要这么搞,但是在Linux操作系统中的gcc是编译不了的)。函数Test_Static_Quote返回的是静态变量,因为静态变量是在整个程序的运行期间都会存在的,所以可以进行引用的操作,并且,定义了serven_4去引用这个返回值,函数Test_Static_Quote()返回值的引用相当于有了个别名,这个别名是serven_4,所以可以对其进行改变数值赋值。

    上面的代码运行结果:

4. 引用和多态

        首先,我们得了解多态是什么?多态是指一个子类继承了父类,然后对父类的方法进行了重写的操作。

class serven;
class serven_1: public serven{...};
​
serven_1 Ser_1;
serven &Ser = Ser_1;    

        Ser是基类引用指向派生类,它只能来访问派生类对象中从基类继承的成员变量和成员函数。如果serven类中定义有虚函数,并且在serven_1类中重写了这个虚函数,就可以通过Ser产生多态效果。

最后,我们来看一下指针和引用的区别

指针引用
初始化可以为空初始化不能为空
可以指向别的变量不能引用别的变量
sizeof得到的是指针本身的大小sizeof是所引用的变量(对象)的大小
指针++是地址++引用++是数值++

        动态分配内存的对象或者是分配内存一般使用指针,引用可能会引起内存泄漏。

关注公众号 “三贝勒文子” ,每天学习C++

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三贝勒文子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值