C++学习(三):引用&

引用

记录自己学习C++的点点滴滴,为了自己更好的复盘和回顾,如果可以帮助到你,我将不胜荣幸!!!



一、引用是什么

C++引用的提出其实就是为了减少C中指针的使用,引用并不是定义一个新的变量,而是给变量取一个别名;形如:

int number = 10;
int & ref = number;

引用的符号就是 & ,和C语言的取地址符号是一样,但是他们的作用并不一样,区分他们的一个关键点就在于&前是否有类型,如果&前有地址那么这便是用于引用而不是用于取地址;

二、引用的使用

引用在使用时,我们需要注意:

引用在定义时必须要初始化,引用一经绑定就不会改变指向。

其实这和上一小节中我们谈到的指针常量是一样的,我们其实可以想到引用的实现的,但是编译器是不会为引用开辟内存空间的,它和它引用的变量是共用同一块内存空间的;并且对引用的操作与对引用的变量操作是等价的;

其实这一点在进行值交换函数时是非常有用的,我们可以对比以下C中实现两个值交换函数与C++中实现两个值交换函数:

//c语言实现值交换函数
void  swap(int * number1,int *number2)
{
	int tmp = *number1;
	*number1 = *number2;
	*number2 = tmp;
}
//C++实现值交换函数
void swap(int &ref1, int &ref2)
{
	int tmp = ref1;
	ref1 = ref2;
	ref2 = tmp;
}

我们发现引用的引入相比较用指针的方式更加方便且容易理解,同时这里也引出了我们接下来要讨论的一个话题——当引用作为函数返回值时,如果返回的是全局变量、堆空间以及栈空间分别是怎样的呢?

三、引用作为函数返回值

3.1、全局变量

当引用作为全局变量的函数返回值时,不会发生拷贝操作,并且对引用的操作就相当于对全局变量的实体进行操作;

   15 //引用作为全局变量的返回值
   16 int arr[10] = {1, 2, 3, 4};
   17 int &getIndex(int idx)
   18 {
   19     return arr[idx];
   20 }
   21 void test1()
   22 {
   23     int &ref = getIndex(0);
   24     cout << "getIndex(0) = " << getIndex(0) << endl;
   25     getIndex(0) = 100;
   26     cout << "getIndex(0) = " << getIndex(0) << endl;                                            
   27     cout << "arr[0] = " << arr[0] << endl;
   28 }    

3.2、堆空间

堆空间可以用局部变量进行举列,由于局部变量是有生存周期的,随着函数的结束,堆空间上的局部变量也就自动消失了,因此我们在使用引用作为堆空间的返回值时,编译器会发生报错;

   30 // 引用作为堆空间的返回值
   31 int &fun1()
   32 {
   33     int number = 100;
   34     return number;
   35 }
   36 void test2()
   37 {
   38     int &ref = fun1();
   39     cout << "number = " << ref << endl;
   40 }

会发生如下的报错:

reference.cpp: In function ‘int& fun1()’:
reference.cpp:33:9: warning: reference to local variable ‘number’ returned [-Wreturn-local-addr]
     int number = 100;
         ^~~~~~

这里也就引出来了函数返回类型是引用的前提条件:返回的引用必须是生命周期大于函数本体的实体

这时候大家也就会不由得的联想到我们最常见的栈空间上的变量了,按道理说栈空间上的变量不会随着函数的消失而消失,那么他的生命周期肯定也就大于函数的生命周期了,应该是可以用引用作为函数的返回类型;

那么栈空间在将引用作为函数返回类型时会存在哪些问题呢?

3.3、栈空间

直接上代码

   43 int &getHeapData()
   44 {
   45     int *pInt = new int(100);
   46     return *pInt;
   47 }
   48 void test3()
   49 {
   50     int &ref = getHeapData();
   51     cout << "getHeapData() = " << getHeapData()  <<endl;
   52     cout << "ref = " << ref << endl;
   53 }
getHeapData() = 100
ref = 100

可以看到堆空间时可以使用引用作为返回类型的,但是大家有没有发现什么问题呢?

我们在函数中new了一个堆空间,我们有delete这个堆空间吗?,如果没有那会发生一个什么样的问题呢?

显然,内存泄漏了,我们可以通过delete操作解决这里的内存泄露,但是一般我们在拿到这种函数的api时,默认他已经做好了相应的内存管理工作,不会专门再去做delete销毁堆空间,而且你也不能保证别人就用的是new啊!所以不要返回堆空间的引用,除非有完善的自动回收机制;

这里最后完善一下上面发生内存泄漏的问题:

   48 void test3()
   49 {
   50     int &ref = getHeapData();
   51     cout << "getHeapData() = " << getHeapData()  <<endl;
   52     cout << "ref = " << ref << endl;
   53 
   54     delete &ref;
   55 }


总结

引用在C++的使用是十分常见的,同时这也是C与C++的一个不同之处

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值