引用的概念:
引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。
引用定义的格式:
类型& 引用变量名 = 已定义过的变量名;
例如:
int a = 10;
int& b = a;//b是a的引用,b是a的别名
引用的特点:
1.一个变量可以取多个别名
2.引用必须初始化
3.引用只能在初始化的时候引用一次,不能改变再引用其他变量
引用又可分为const引用和非const引用
- const引用只读,与绑定对象是否为const无关。
- 非const引用可读可写,只可与非const对象绑定。
- 非const引用只能绑定到与该引用同类型的对象,const引用则可以绑定到不同但相关的类型的对象或绑定到左值,const引用可以初始化为不同类型的对象或者初始化为右值,如字面值常量。
int d1 = 4;
const int &d2 = d1;
d1 = 5; //d1改变,d2的值也会改变
//d2 = 6; //不能给常量赋值
const int d3 = 1;
const int& d4 = d3;
//int& d5 = d3;
const int& d6 = 5;//常量具有常性,只有常引用可以引用常量
double d7 = 1.1;
//int& d8 = d7;//d7是double类型,d8是int类型,d7赋值给d8时要生成一个临时变量
//也就是说d8引用的是这个带有常性的临时变量,所以不能赋值
const int& d9 = d7;
在C++中有三种函数传参的方式
1.值传递
如果形参为非引用的传值方式,则生成局部临时变量接收实参的值,传递是单向的。如果在执行函数期间,形参的值发生变化,并不传回给实参。因为在调用函数时,形参和实参不是一个存储单元。
2.引用传递
如果形参为引用类型,则形参是实参的别名,和实参是一个变量,调用函数时,形参指向实参变量单元。这种通过形参引用可以改变实参的值。引用传参可以减少空间浪费提高效率。
3.指针传递
如果形参是指针类型,实参是一个变量的地址,调用函数时,形参指向实参变量单元。这种通过形参指针可以改变实参的值。
引用做返回值
引用做返回值必须遵循以下规则:
1.不能返回局部变量的引用,局部变量会在函数返回后被销毁
2.不能返回函数内部new分配的内存的引用,虽然不存在局部变量的被动销毁问题,但是函数返回的引用只是作为一个临时变量出现,并没有被赋予一个实际的变量,导致引用所指向的空间无法释放,造成内存泄漏
3.可以返回类成员的引用,但最好是const。主要原因是当对象的属性与某种业务规则相关联的时候,其赋值常常与某些其他属性或者对象的状态相关联,因此有必要将赋值操作封装在一个业务规则中,如果其对象可以获得该属性的非常量引用(或指针),那么对于该属性的单纯赋值就会破坏业务规则的完整性
4.引用与一些操作符的重载。流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout<<”hello world”<<endl;
因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。但+-*/四则运算符不能返回引用,需要返回一个对象
5.如果返回对象出了当前函数的作用域依旧存在,则最好使用引用返回,因为这样更高效
通过汇编看传值返回和传引用返回
#include<iostream>
//传引用返回
int& Add(int d1, int d2)
{
int ret = d1 + d2;
return ret;
}
void Test()
{
int& ret = Add(1, 2);
}
//传值返回
int Add(int d1, int d2)
{
int ret = d1 + d2;
return ret;
}
void Test()
{
int ret = Add(1, 2);
}
int main()
{
Test();
system("pause");
return 0;
}
指针和引用的区别:
1.引用只能在定义时初始化1次,之后之后不能改变指向其他变量(从一而终);指针变量的值可变。
2.指针是一个实体,需要分配内存空间。引用只是变量的别名,不需要分配内存空间。
3.引用必须指向有效的变量,指针可以为NULL。
4.sizeof指针对象和引用对象的意义不一样,sizeof引用得到的是所指向的变量的大小,ersizeof指针是对象地址的大小。
5.指针和引用自增和自减意义不一样。(指针是指向下一个空间,引用是引用的变量值+1)
6.引用访问一个变量是直接访问,而指针访问一个变量是间接访问。
7.相对而言,引用比指针更安全。