1.引用的概念及用法
一个对象的引用就是这个对象的别名,所以对一个对象的进行操作,和直接对这个对象操作的效果是一样的。
如何创建引用? 对象类型 & 引用名 = 对象名;
引用的特点:
- 引用为一个对象的别名,所以不占内存
- 引用必须初始化,并且不能为NULL
- 引用初始化结束后,不能再次改变
代码如下:
#include
<iostream>
int
main()
{
int
a = 10;
int
*pa = &a;
int
&b = a;
std::cout
<<
a
<<
std::endl;
std::cout
<<
*pa
<<
std::endl;
std::cout
<<
b
<<
std::endl;
std::cout
<<
&a
<<
std::endl;
std::cout
<<
pa
<<
std::endl;
std::cout
<<
&b
<<
std::endl;
std::cout
<<
sizeof
(a)
<<
std::endl;
std::cout
<<
sizeof
(*pa)
<<
std::endl;
std::cout
<<
sizeof
(b)
<<
std::endl;
system(
"pause"
);
return
0;
}
2.引用做参数
我们知道,在交换两个值时不能传值,会产生临时变量,交换的是临时变量的值,实际两个变量的值并没有交换,之前的做法是传指针,现在也可以用传引用的方式交换两个变量的值,函数的参数在调用的时候被初始化,也就是说形参是实参的一个别名,那么操作形参就是对实参的操作
#include
<iostream>
void
Swap(
int
& a,
int
& b) {
int
c = a;
a = b;
b = c;
}
int
main()
{
int
a = 4;
int
b = 2;
std::cout <<
"(a,b) ==> ("
<< a <<
","
<< b <<
")"
<< std::endl;
Swap(a, b);
std::cout <<
"(a,b) ==> ("
<< a <<
","
<< b <<
")"
<< std::endl;
system(
"pause"
);
return
0;
}
3.引用做返回值
一个普通的返回值,在函数栈帧销毁是会被保存到一个地方(寄存器,或内存),也就是说会产生一个副本,如果返回一个引用的话就不会产生这个副本,节省资源,提高效率。 但是要注意几点:
-
不能返回局部变量的引用。这条可以参照Effective C++[1]的Item 31。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。如【例5】中的第2种情况出现编译错误。
- 不能返回函数内部new分配的内存的引用。这条可以参照Effective C++[1]的Item 31。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
-
可以返回类成员的引用,但最好是const。这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
4.汇编层看引用的特性
#include
<iostream>
int
main()
{
int
a = 10;
int
*pa = &a;
int
& b = a;
system(
"pause"
);
return
0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/7d9562516883ebd90646e9eb29a801c2.png)
从汇编的角度看,这个引用中保存的就是a的地址吗,引用就是一个指针变量,为什么底层都是指针,而在语法上不同呢?虽然底层实现是指针,但是在上层对这个指针加以约束,就变得更加安全,在用指针的眼光看待上面的代码,其实也行得通。
5.引用和指针的区别
指针可以初始化也可以不初始化,引用必须初始化,所以引用不会出现NULL
指针可以指向任意地址,而引用在初始化之后就不能再次成为另一个对象的别名,所以传参时不会访问非法内存
指针占4个或8个字节,而引用只是一个别名,不占内存
指针可以自增或者自减(++ --),而对引用来说没有意义,假如b是a的别名,使用b++,实际就是a++
指针有多级指针,而引用只有一级,可以是 int& b = a; 但不可以int &&c = b;后一种方法是错误的