1、引用的概念和定义
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。
语法:类型 & 引用别名=引用对象;注意:类型必须与引用对象的类型一致。
代码示例:
#include<iostream>
using namespace std;
int main()
{
int a = 0;
//引用b,c是a的别名
int& b = a;
int& c = a;
//也可以给别名b取别名,d相对于还是a的别名.
int& d = b;
d = 11;
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
return 0;
}
结果:
2、引用的特性
(1)引用定义时必须初始化
示例:
(2)一个变量可以有多个引用。
代码示例:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& b = a;//b是a的别名
int& c = a;//c是a的别名
int& d = a;//d是a的别名
return 0;
}
(3)引用一旦引用一个实体,再不能引用其他实体。
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& b = a;
int d = 12;
b = d;//这是赋值操作,而不是b引用c。是把d的值12赋值给b,而b是a的别名,所以a的值是12;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
return 0;
}
结果:
3、引用的使用
(1)引用在实践中主要是用于引用传参和引用做返回值,以此减少拷贝,提高效率。并且在函数传参中使用引用时,改变形参同时也可以同时改变被引用对象。
函数传参:
//用引用传参来实现两个数字的交换
#include<iostream>
using namespace std;
void swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
int main()
{
int a = 11;
int b = 89;
cout << "交换前:" << endl;
cout << "a= " << a << endl;
cout << "b=" << b << endl;
cout << "交换后:" << endl;
swap(a, b);
cout << "a= " << a << endl;
cout << "b=" << b << endl;
return 0;
}
结果:
(2)引用传参与指针传参功能是类似的,引用传参相对更方便一些。
(3)引用和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不能替代。
4、const引用
(1)可以引用一个const对象,但是必须用const引用。const引用可以引用普通对象,因为对象的访问权限在引用过程中可以缩小,但是不能放大。
例如:
//const引用
#include<iostream>
using namespace std;
int main()
{
const int a = 10;//a被const修饰,此时a只可读不可修改。
int& c = a;//报错
return 0;
}
结果:
用const引用:
//const引用
#include<iostream>
using namespace std;
int main()
{
const int a = 10;//a被const修饰,此时a只可读不可修改。
const int& c = a;//不报错
return 0;
}
代码:
#include<iostream>
using namespace std;
int main()
{
int a = 12;
const int& b = a;//引用的时候权限可以缩小,但是权限不能放大
//注意:a的权限没有改变,只是以权限缩小的方式定义了引用,不影响原来的权限
a++;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
return 0;
}
结果:
(2)需要注意的是类似:int& rb=a*3;double d=12.34;int & rd=d;这样一些场景下a*3的结果保存在一个临时对象中,int& rd=d;也是类似,在类型转换中会产生临时对象存储中间值,也就是说:rd和rb引用的都是临时对象,而C++规定临时对象具有常性(常性即:数据只可读,不能修改),所以这里就触发了权限放大,必须要用常引用才可以。
(3)在(2)中所说的临时对象就是编辑器需要一个空间暂存表达式的求值结果是临时创建的一个未命名的对象,C++中把这个未命名对象叫做临时对象。
注意:权限的放大与缩小时在引用和指针之间才会有。
代码:
#include<iostream>
using namespace std;
int main()
{
const int a = 10;
//int& ra = a;//权限的放大
int b = a;//只是赋值操作,没有权限的放大这么一说
return 0;
}
引用还可以引用字面量:
#include<iostream>
using namespace std;
int main()
{
const int& rb = 11.0;//引用还可以引用字面量
return 0;
}
5、指针与引用的关系
C++中指针和引⽤就像两个性格迥异的亲兄弟,指针是哥哥,引⽤是弟弟,在实践中他们相辅相成,功
能有重叠性,但是各有⾃⼰的特点,互相不可替代。
(1)语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
(2)引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
(3)引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。
(4)引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。
(5)sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台下
占4个字节,64位下是8byte)
(6)指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。