文章目录
- 1、引用概念
- 2、引用特性
- 3、常引用
- 4、引用的使用场景
- (1)做参数
- (2)做返回值
 
 
 
1、引用概念
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。
类型& 引用变量名(对象名) =引用实体;
注意:引用类型必须和引用实体是同种类型的
void TestRef()
{
    int a = 10;
    int& ra = a;//<====定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}
//两者地址一致
2、引用特性
引用在定义时必须初始化
一个变量可以有多个引用
引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{
   int a = 10;
   // int& ra;   // 该条语句编译时会出错,因为它未初始化
   int& ra = a;
   int& rra = a;
   printf("%p %p %p\n", &a, &ra, &rra);  
}
3、常引用
意思就是const类型的引用也要const,不能const int 使用int引用。
void TestConstRef()
{
    const int a = 10;
    //int& ra = a;   // 该语句编译时会出错,a为常量
    const int& ra = a;
    // int& b = 10; // 该语句编译时会出错,b为常量
    const int& b = 10;
    double d = 12.34;
    //int& rd = d; // 该语句编译时会出错,类型不同
    const int& rd = d;
}
int Count()
{
	int n = 0;
	n++;
	return n;
}
int main()
{
	int a = 1;
	int& b = a;
	// 指针和引用,赋值/初始化 权限可以缩小,但是不能放大
	// 权限放大
	/*const int c = 2;
	int& d = c;
	const int* p1 = NULL;
	int* p2 = p1;*/
	// 权限保持
	const int c = 2;
	const int& d = c;
	const int* p1 = NULL;
	const int* p2 = p1;
	// 权限缩小
	int x = 1;
	const int& y = x;
	int* p3 = NULL;
	const int* p4 = p3;
	// 权限只适用于指针和引用,这个是可以的,n和m两个空间是独立的
	//const int m = 1;
	//int n = m;
	const int& ret = Count();//n是临时变量传值返回,不可被修改,加个const才行 
    
    //这部分听不懂,以后遇到重新学习  
	int i = 10;
	cout << (double)i << endl;
	double dd = i;
	const double& rd = i;
	return 0;
}
4、引用的使用场景
(1)做参数
void Swap(int& left, int& right)
{
   int temp = left;
   left = right;
   right = temp;
}
//使用了引用,函数里面改的就是实参,不需要用到取地址再解引用
函数在使用引用时,函数参数是引用int& i,实参也可以使i,因为他们是不同作用域的,可以同名。
形参的改变影响实参。 比如**phead的运用。
(2)做返回值
count 函数调用时,n的返回过程。
第一种是没有static,count的函数栈帧结束后,n的值传给临时变量,这个临时变量是在寄存器或者main函数里面开辟的,此时count函数栈帧被销毁还给操作系统,临时变量再赋值给main函数中的ret。
第二种是有static,其实和第一种差不多,只不过n是放在静态区,n一样要赋值给临时变量。
第三种是传引用返回,直接返回n,而不是传给临时变量。

int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n;
}
下面代码输出什么结果?为什么?
int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);//这里的&去掉,ret依然是c的别名,函数结束后c依然还给了操作系统,ret一定是未知,当然有可能对,取决于第一次栈帧销毁时c的值。 
    Add(3, 4);
    cout << "Add(1, 2) is :"<< ret <<endl;//7
    return 0;
}
//上面是c是局部变量,函数结束后还给了操作系统,此时ret是c的引用别名,所以ret的值是未知的。

注意:如果函数返回时,出了函数作用域,如果返回对象还在()引用返回,如果已经还给系统了,则必须使用传值返回。



















