1.引用
1.1 定义
引用就是变量的别名(并没有重新定义一个变量),通过将声明符写成&d的形式来定义引用类型。需注意的是:
- 一个变量可以有多个别名;
- 引用的变量必须初始化;
- 引用只能在初始化的时候使用一次,不能再引用改变其他变量
如下所示,已定义变量a,b与c相当于a的别名,即a可以叫b,也可以叫c;b、c与a指向同一块空间,当其中一个改变时,其他的值也跟着改变
int main()
{
int a=1;
int &b=a;
int &c=b;
std::cout<<a<<" "<<b<<" "<<c<<std::endl;//1 1 1
b=2;
std::cout<<a<<" "<<b<<" "<<c<<std::endl;//2 2 1
}
注:&在类型之后、变量之前为“引用”;&在比那里之前为“取地址”
1.2 const引用
原则:属性只能被局部缩小,不能被局部放大
(1)常引用量可以引用可被修改的量
int a=2;
const int &b=a;//正确
(2)常量具有常性,只有常引用才能引用常量,可被修改的量不能引用常量
const int a=2;
const int &b=a;//正确
//int &b=a;//错误
(3)e的类型是double,f的类型是int,e赋值给f时系统生成一个临时变量,即这个临时变量具有常性不能被修改,所以不能赋值;
又e和f指向的是两个变量,所以e的改变不影响f
double e=1.2;
const int& f=e;
std::cout<<e<<" "<<f<<std::endl;//1.2 1
e=2.3;
std::cout<<e<<" "<<f<<std::endl;//2.3 1
double e2=1.2;
int &f2=e2;
std::cout<<e2<<" "<<f2<<std::endl;//1.2 1
1.3引用做参数
函数调用中发生的数据传送是单向的。 即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。
当形参和实参不是指针类型时,在该函数运行时,形参和实参是不同的变量,他们在内存中位于不同的位置,形参将实参的内容复制一份,在该函数运行结束的时候形参被释放,而实参内容不会改变。
void swap(int a,int b)
{
int c=a;
a=b;
b=c;
}
int main()
{
int c=10;
int d=20;
swap(c,d);
std::cout<<c<<" "<<d<<std::endl;//10 20
return 0;
}
如果函数的参数是指针类型变量,在调用该函数的过程中,传给函数的是实参的地址,在函数体内部使用的也是实参的地址,即使用的就是实参本身。所以在函数体内部可以改变实参的值。
void swap2(int& a, int& b)
{
int c = a;
a = b;
b = c;
}
int main()
{
int c = 10;
int d = 20;
swap2(c, d);
std::cout << c << " " << d << std::endl;//20 10
return 0;
}
1.4 引用做返回值
int add1(int a, int b)
{
int c = a + b;
return c;
}
int& add2(int a,int b)
{
int c = a + b;
return c;
}
int main()
{
int tmp1 = add1(10, 20);
std::cout << tmp1<< std::endl;//30
int tmp2 = add2(30, 20);
std::cout << tmp2 << std::endl;//50
system("pause");
return 0;
}
出了作用域对象不在---传值返回
出了作用域对象还在---最好传引用返回,提高效率;也可以用传值返回,开销大。
2.指针与引用的区别
(1)概念上不同:指针是地址变量,指向内存中的一个地址;引用是变量的别名,本质上还是与这个变量
(2)其他
- 指针可以为空;引用的变量不可以为空,引用在定义时变量必须初始化,且引用只能在初始化时使用一次,之后不能再指向其它对象
- 指针可以有一级、二级、多级指针,如int **a;引用只能有一级,不存在int &&a
- 有const指针,没有const引用
- 指针++是对指向内存中的地址++;引用++是对这个变量进行++
- “sizeof指针”得到的是指针本身的大小;“sizeof引用”得到的是所指向变量的大小
- 引用做参数传递的是实参本身,指针做参数传递的是实参的地址
不是实参的拷贝,形参相当于实参的别名,对形参修改就是对实参修改;
指针做参数传递的是实参的地址,指针实际上是无存储实参内存单元里的数据,从而达到对实参修改的目的。
- 指针比引用更灵活,引用比指针更安全
对++,--这样的操作,引用永远只能指向一个地方,而且是在初始化的时候指定,而指针可以指向其它地方。
调用某一类型空悬指针(指针的值不为空,但它指向的内容有可能被delete了),指针不会知道它所指的内容为空,调用时有可能导致系统崩溃。而引用所指内容绝对不能为空,有效防止了这一点。
3.有了指针为什么还要有引用
“引用传递”的性质像“指针传递”,而书写方式像“值传递”。实际上“引用”可以做的任何事情“指针”也都能够做,但是指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。
指针经常犯的错误有:1,操作空指针,2,操作野指针,3,不知不觉改变了指针的值,而后还以为该指针正常。如果我们要正确的使用指针,我们不得不人为地保证这三个条件。而引用的提出就是解决这个问题。引用区别于指针的特性是:1,不存在空引用(保证不操作空指针),2,必须初始化(保证不是野指针),3,一个引用永远指向他初始化的那个对象(保证指针值不变)。所以引用的提出就是尽可能减少错误的产生。
使用原则:尽可能使用引用,不得已时使用指针。