1.引用的概念及用法
引用:引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。
例如:
int & b = a;
b是a的引用,即b是a的别名。
引用的特点:
a.一个变量可取多个别名
b.引用必须初始化(int &b;不知道b是谁的别名)
c.引用只能在初始化的时候引用一次,不能改变为再引用其他的变量(例如,b是a的别名就只能是a的别名,不能在成为其他变量的别名)
引用的用法:
void Test(){
int a = 1;
int& b = a;
cout<<"a:address->"<<&a<<end1;
cout<<"b:address->"<<&b<<end1;
显然,打印出两个的地址是一样的。
const引用:
const 引用可以与常量绑定也可以与变量绑定,只是不能通过const引用来改变绑定对象的值;如下:
void Test(){
int a = 1;
const int& b = a;
a = 6;//正确
b = 5;//错误,不能通过引用改变a的值
const int & c = 5;//正确,常量具有常性,只有常引用可以引用常量
}
非const引用不能与const对象绑定,因为常量a的值不可改变,但却可以通过非const引用来改变常量a的值,这样做是错误的,如下:
void Test(){
const int a = 1;
int& b = a;//错误,非const引用不能绑定到const对象
当const引用绑定类型不匹配,会发生什么?
void Test(){
double a = 1.1;
const int & b = a;
执行const int &b=a时,发生了这种情况:const int temp=a;const int &b=temp;所谓临时变量就是编译器需要一个空间暂存表达式的求值结果时临时创建的未命名的对象。而假如b不是一个常量引用,在对b赋值时,就会改变b所绑定对象的值。但此时绑定的对象是一个临时的量,它没有名字,而不是绑定了a。既然b绑定了a,肯定是想通过b改变a的值,否则干嘛将a绑定到b呢?但是此时非const修饰的b改变不了a的值,那绑定也就无意义,所以编译器不允许这样做。
总之,大家记住一点,跨类型引用临时变量必须加const
2.引用作为参数
引用传递,传递的是内存地址,修改后会改变内存地址对应储存的值。
先看代码:
void Swap(int & left,int & right){
int tmp = left;
left = right;
right = tmp;
}
这里采用引用传递,如果形参为引用类型,则形参是实参的别名。
传引用的效率比传值效率高.
注意,当不希望函数改变参数的值时,尽量使用常引用传参。
void Data(const int& x);
3.引用做返回值
首先,需要了解什么时候用传值返回,什么时候用传引用返回?
当函数返回时,出了作用域值还在,用传引用返回,来提高效率;出了作用域值不在,采用传值返回。
传引用:将返回值的别名返回;
传值:给返回值拷贝一份返回;
int& Add(int d1,int d2){
int ret = d1 + d2;
return ret;
}
4.指针和引用的区别和联系
a.引用只能在初始化时一次,之后不能改变指向其他变量(从一而终);
指针变量的值可变;
b.引用必须指向有效的变量,指针可以为空;
c.sizeof指针对象和引用对象的意义不一样。sizeof引用得到的是所指向的变量的大小,而sizeof指针是对象地址的大小。
d.指针和引用自增(++)自减(–)意义不一样。
e.相对而言,引用比指针更安全。
总结:
指针比引用更灵活,但也更危险。使用指针时一定要注意检查指针是否为空。指针所指的地址释放以后最好置0,否则可能存在野指针问题。