浅谈C++引用的使用以及底层原理

1、引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

类型& 引用变量名(对象名) =引用实体;

注意:引用类型必须和引用实体同种类型

void TestRef()
{
    int a = 10;
    int& ra = a;//<====定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}
//两者地址一致

2、引用特性

  1. 引用在定义时必须初始化

  2. 一个变量可以有多个引用

  3. 引用一旦引用一个实体,再不能引用其他实体

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,而不是传给临时变量。

image-20240310104611202.png

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的值是未知的。

image-20240309101421894.png

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

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hhh __灏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值