我们经常会给同学起外号,"小胖"白皮猪"等等,引用简单理解就是给一个数据对象取的别名。 &有多层含义:
位运算,这个前面我们有笔记
取地址
引用 int a= 60; int&b = a; 引用仅仅是给已存在数据对象的一个别名,程序不会为引用开辟内存空间,与引用的原型共用一块内存地址 格式: 类型&引用名 = 引用实体
定义引用时必须初始化
没有空引用
一个变量可以有多个引用
对比一下交换函数用引用和指针做参数的区别
#include<iostream>
int swap(int* a, int* b);
void swap01(int& a, int& b);
int main()
{
int a = 10; int b = 20;
swap(&a, &b);
std::cout << "a = " << a << " b = " << b<<'\n';
swap01(a, b);
std::cout << "a = " << a << " b = " << b;
}
int swap(int* a, int* b)
{
if (a!=NULL && b!=NULL)
{
int temp = *a;
*a = *b;
*b = temp;
}
return 0;
}
void swap01(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
指针比引用复杂的多,出错的概率也比较大,因此我们在平时能不用指针就不用指针,比如这里的深浅拷贝,就可以用引用代替指针。
从语法规则上讲,指针变量存储某个实例(变量或对象)的地址; 引用是某个实例的别名。
程序为指针变量分配内存区域;而不为引用分配内存区域。
解引用是指针使用时要在前加“*”;引用可以直接使用。
指针变量的值可以发生改变,存储不同实例的地址; 引用在定义时就被初始化,之后无法改变(不能是其他实例的引用)。
int a1 = 10, b1 = 20;
int* ip = &a1;
ip = &b1;
int& c = a1;
c = b1; //b的值给c实则是把b的值给a,将a的值改为20
std::cout << "a1 = " << a1 << " b1 = " << b1;
指针变量的值可以为空(NULL,nullptr);没有空引用。
指针变量作为形参时需要测试它的合法性(判空NULL); 引用不需要判空。
对指针变量使用"sizeof"得到的是指针变量的大小;对引用变量使用"sizeof"得到的是变量的大小。
理论上指针没有级数的限制,但引用只有一级。
对引用的操作直接反应到所引用的实体(变量或对象)。 对指针变量的操作,会使指针变量指向下一个实体(变量或对象)的地址;而不是改变所指实体(变量或对象)的内容。
不可以对函数中的局部变量或对象以引用或指针方式返回。只有当变量生存期不受函数影响就可以返回地址
引用变量
int main()
{
int a = 10;
int & b = a;
const int& c = a;
b += 10;
a += 10;
c += 10;
return 0;
}
c这里会报错,因为这里的c是const也就是不可修改的。
引用常量
int main()
{
int a = 10;
const int b =20;
int& x = a;
int& y = b; //error 不安全
const int& y = b; //ok
const int& z =10; //ok
return 0;
}
引用字面常量 引用字面常量时,分两步走,首先定义一个临时量 去引用临时量 不是引用真实的字面常量10。
int a = 10;
const int &b =10;
数组引用 要申明数组引用,必须知道数组的大小
int main()
{
int a = 10;
int b = 10;
int ar[5] = { 1,2,3,4,5 };
int& x = ar[0]; //ok
int(&x)[5] = ar; //ok 没有[5]无法编译通过
return 0;
}
指针引用
int a = 100;
int* p = &a;
int*& rp = p;
std:: cout << a << std::endl;
std::cout << *p << std::endl;
std::cout << *rp << std::endl;
std::cout << p << std::endl;
std::cout << rp << std::endl;
return 0;