一.引用
1. 定义:就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。
引用的声明方法:定义引用ra,它是变量a的引用,即别名。
类型标识符 &引用名=目标变量名;如:
int a;
int &ra=a;
在此处,“&”为引用运算符,ra是整形变量a的别名,这样,对ra的操作实际上就是对a的操作,对ra的赋值就是对a的赋值。ra = 999;(a = 999;)
2.引用的地址
#分别取a与其别名ra的地址并输出,会发现两者存储地址是一样的,所以对ra的操作实际上就是对a的操作。
3.引用就是别名常量
#引用这个别名是专属于某一变量名的,引用受影响则其原变量也要受影响,一同被赋值。
4.引用对象
#可以定义一个对象的别名,如:
Human Mike;
Human &rMike = Mike;
#但是不能定义一个类的别名,如:
Human &rHuman = Human;(×)
因为Human是一种类型,它没有具体的内存地址。
一个对象的引用和它的使用方法一样,用类的成员运算符(.)来访问成员数据和方法。
二.传递参数
1.按值传参
如交换函数swap,按值从主函数中向执行函数中传参,只是对参数的副本操作而已,执行完会将副本的结果释放掉,主函数最后得不到正确的结果。
2.按指针传参
void swap(int *a,int *b)
swap(&a, &b);
由a和b的内存地址间接访问a和b的值,编译器不用在栈中创建两个值得副本,只要传递a和b的地址即可,那么在函数中对*a和*b的操作,就是对a和b原始值的操作。
3.按引用传参
void swap(int &a,int &b)
swap( a, b);
4.用指针返回多值
int func(int *a, int *b, int *c)
func(&a, &b, &c);
5.用引用返回多值
int func(int &a, int &b, int &c)
func(a, b, c);
三.传递对象
1.用值传递对象
按值传递对象,假如该对象的数据较多时,这种拷贝带来的内存开销是非常大的,不可取。
2.用指针传递对象
Iint main()
{
A a;
func(&a);
return 0;
}
A *func(A *one)
{
return one;
}
3.使用const指针来传递对象
采用指针来传递对象,虽然可以避免调用复制构造函数和析构函数,但是由于它得到了该对象的内存地址,可以随时修改对象的数据,因此它实际上破坏了按值传递的保护机制。
不过对此我们仍然有解决办法,那就是用const指针来传递对象,这样可防止任何试图对该对象的数据进行的操作行为,并且保证返回一个不被修改的对象。
const A *const func(const A *const one)
{
cout<<one->get()<<endl;
return one;
}
4.使用引用来传递对象
A &func(A &one)
{
cout<<one.get()<<endl;
return one;
}
5.引用与指针的区别
#指针可以为空,引用不能为空;
#指针可以被赋值,引用不可以被赋值;
#指针可以指向堆中空间,引用不可以指向堆中空间。
#指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
#引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”。
#引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有的, 前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)。
#“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小。
#指针和引用的自增(++)运算意义不一样。
#引用是类型安全的,而指针不是 (引用比指针多了类型检查)。
四.引用总结
(1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。
(2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。
(3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
(4)使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。