引用
变量名,本身是一段内存的引用,即别名(alias).引用可以看作一个已定义变量的别名
引用的语法: Tvpe& name = var;
类型& 引用变量名称 = 变量名称
这就是引用变量的定义。&和类型结合称之为引用符号,不是取地址的符,代表别名的意思。
规则
1.&在此不是求地址运算,而是起标识作用
2.类型标识符是指目标变量的类型
3.必须在声明引用变量时进行初始化
4.引用初始化之后不能改变
5.不能有 NULL引用。必须确保引用是和一块合法的存储单元关联
6.可以建立对数组的引用,
int main()
{
int a = 10;
int b = a;
int& c = a;
return 0;
}
引用的特点
int main(void)
{
int a,b;
int &r = a;
int &r = b; //错误,不可更改原有的引⽤关系
float &r = b;//错误,引⽤类型不匹配 cout<<&a<<&r<<endl; //变量与引⽤具有相同的地址。
int &ra = r;//可对引⽤更次引⽤,表⽰a变量有两个别名,分别是r和ra
return 0;
}
int main()
{
int a = 10;
const int b = 20;
const int& cr = a; //引用变量
const int& cb = b; //引用常量
const int& cc = 10; //引用字面常量
int& ra = a; //普通引用只能引用变量
int& raa = b; //普通引用不可以引用常量
int& raaa = 10; //普通引用不可以引用字面常量
}
引用作为形参代替指针
最常见看见引用的地方是在函数参数和返回值中。当引用被用作函数参数的时,在函数内对任何引用的修改,将对还函数外的参数产生改变。当然,可以通过传递一个指针来做相同的事情,但引用具有更清晰的语法。
如果从函数中返回一个引用 必须像从函数中返回一个指针一样对待。当函数返回值时引用关联的内存一定要存在
//使用指针交换两个整型值
void Swap(int* ap, int* bp)
{
assert(ap != nullptr && bp != nullptr);
int tmp = *ap;
*ap = *bp;
*bp = tmp;
}
int main()
{
int a = 10,b = 20;
Swap(&a, &b);
}
//使用引用交换两个整型值
void Swap(int& a, int& b)
{
int tmp = a;
a = b;
b = tmp;
}
int main() //形参的改变改变实参
{
int x = 10, y = 20;
Swap(x, y);
}
其他引用
void funa(int x) {}
void funb(int& b){} //形参的改变改变实参
void func(const int& b) {} //“const”不需要形参的改变改变实参
int main()
{
int a = 10;
funa(a); //对x的修改并不会修改到a本身 x是a的副本
funb(a); //b是a的别名 引用的时候对b的改变会影响到a
func(a); //常引用 不能通过b的改变去改变a
return 0;
}
数组引用
int main()
{
int ar[5] = { 1,2,3,4,5 };
//数组名代表整个数组的意义 :数组名代表的是类型和大小
sizeof(ar); //20
int(& br)[5] = ar; //引用数组
int(*p)[5] = &ar;
int* s[5] = {}; // 数组里面有五个元素 每个元素都是指针 指针是int类型 从右向左解释
//int& cr[5]; error 引用不需要空间 数组需要空间 矛盾
return 0;
}
const引用(常量引用)
//const引用
int main()
{
int a{ 10 };
const int b{ 20 }; //常变量
int& x = a; //普通引用引用普通变量
int &x = b; //error 不能拿普通引用引用常变量
//常性引用是万能引用
const int& x = b; //ok 常引用可以引用常变量
const int& y = a; //ok 常引用可以引用普通变量,y只能读取a的值,不能通过y去修改a的值
const int& z = 10; //ok 常引用可以引用字面常量
return 0;
}
int main()
{
int a = 10, b = 20;
int* const p = &a; //p本身不能改
int *& s1 = p; //不能编译通过 :s1指针的引用 s1是p的别名 s1自身改 p也要改
const int *&s2 = p; //不能编译通过:const修饰指向 s2是p的别名 s2自身可以改变
int* const &s3 = p; // 可以编译通过:const约束常引用 s3自身不能被改
const int* const &s4 = p; // 可以编译通过:const约束常引用 s4自身不能被改
}
常量引用注意:
字面量不能赋给引用,但是可以赋给 const 引用
const 修饰的引用,不能修改
结论:
1)const int & e 相当于 const int * const e
2)普通引用 相当于 int *const e
3)当使用常量(字面量)对const引用进行初始化时,C++编译器会为常量值分配空间,并将引用名作为这段空间的别名
4)使用字面量对const引用初始化后,将生成一个只读变量
从汇编层次理解引用与指针变量的区别