C++学习笔记--引用

在进入正题前先回顾一下什么叫做变量。变量是一段连续物理空间的别名,在程序中通过变量来申请并命名存储空间,同样的通过变量也能使用一段存储空间。那么问题来了,一段连续的存储空间只能有一个别名吗?答案是否定的。

在C++中增加了引用的概念,引用可以看做一个已定义变量的别名,另一种变量的表现形式,它是个名词,用法如下:type& var_name = var;普通引用在定义时需要用同类型的变量进行初始化。例如:int a = 1;  int& b = a;  b = 10; 此处操作b就等同于操作a。并且a和b指向的是同一片空间。上一节提到过三目运算符的可能返回都是变量时,返回的是变量本身,实际上返回的就是引用,它可以作为左值使用。

一、引用作为变量别名而存在,因此在一些场合可以代替指针,但是相对于指针来说具有更好的可读性和实用性。两个变量交换在C中实现需要用到指针,但是在C++中可以使用引用来完成同样的功能,看看具体实现:

void swap(int* a,int* b)               
{  
	int t = *a;                                    
	*a = *b;         
	*b = *t; 
}   
void swap(int& a, int& b)
{
	 int t = a; 
	a = b;
	b = a;
}

第一种使用指针实现,形参是指针变量;第二种使用引用实现,形参是传入两个引用。比较一下,是不是引用实现更符合人们的阅读习惯也更具实用性,调用的时候不需要对变量取地址传入函数。但是需要注意的一点是函数中的引用形参不需要进行初始化,在函数调用传入实参时进行初始化,这和普通引用的使用有所区别。

二、在C++中可以声明const引用,它有什么作用呢?可以使一个变量具有只读属性,比如:

{
	int a = 4;
	const int& b = a;
	int* p = (int*)&b;
	
	b = 5;//操作错误,只读
	
	*p = 5;//正确,间接修改
}
注意, 它还是变量,只是编译器不允许它作为左值使用,并且只有这一种用法,比较于C中的const简单许多

当使用常量对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段存储空间的别名,例如:

{
	
	const int& b = 1;
	int* p = (int*)&b;
	
	b = 5;//操作错误,只读
	
	*p = 5;//正确,可以当做变量使用间接修改值
}

所以,使用常量对const引用初始化后将生成一个只读变量

了解了一些引用的用法后我们思考一个问题,引用既然是变量的别名,那么引用有自己的空间吗?

struct TRef
{
    char& r;
};

int main(int argc, char *argv[])
{ 
    char c = 'c';
    char& rc = c;
    TRef ref = { c };
    
    printf("sizeof(char&) = %d\n", sizeof(char&));
    printf("sizeof(rc) = %d\n", sizeof(rc));
    
    printf("sizeof(TRef) = %d\n", sizeof(TRef));
    printf("sizeof(ref.r) = %d\n", sizeof(ref.r));

    return 0;
}
最后打印出来的结果是多少?

首先来分析一下,第一条打印语句,打印sizeof(char&)结果,char&定义出来的是一个变量的别名,所以sizeof(char&) <==>sizeof(char),打印出1;第二条打印语句中rc是c的别名,所以大小相等,都为1;第三条暂时还不清楚,但是我认为不会是0,为什么?在C中一个空结构编译器都还为其分配一个字节,C++兼容C,肯定这里不会是0;第四条打印语句中ref.r用变量c初始化,所以他是c的别名,所以也是一个字节,那么让我们看看他的输出结果吧!!!



答案是4,是不是想到了指针也是四个字节了,那么继续往下走。

没错,引用在C++中内部实现就是一个指针常量。type& name; 等价于type* const name;操作引用时在C++的内部实现其实就是操作一个指针常量,所以引用在定义时就占用和指针一样大小的空间,但是C++由于防止使用指针带来的易错性所以就使用引用作为变量的别名,在使用上就隐藏了引用的存储空间这个细节。

下面看一下由定义引用并初始化生成的汇编代码,看看编译器内部是如何实现的。


可以看到char& b = a;的汇编代码是将变量a的地址赋值给引用b所在的四个字节的连续存储空间,所以我们也能证实在编译器内部引用的实现就是通过指针完成的。 C++的引用旨在大多数情况下代替指针,能够避开由于指针操作不当而带来的内存错误,简单好用,功能也比较强大。

最后提醒一句,函数作为返回值返回引用时可以返回全局或静态变量的引用比如static类型的,因为static类型的变量保存在全局数据区,函数释放后变量仍然存在,所以我们又知道了,函数不能返回局部变量的引用,原因就是函数调用结束后它所在的那片内存空间就会被释放,返回的引用就无效或随机的,这样操作也是很危险的,操作返回来的地址可能会引起巨大的BUG。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值