2

C++引用详解_萌新的日常的技术博客_51CTO博客

 1 year ago
source link: https://blog.51cto.com/u_15787387/5868511
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

C++引用详解

精选 原创

萌新的日常 2022-11-18 15:44:38 ©著作权

文章标签 #include 赋值 f5 文章分类 C/C++ 编程语言 yyds干货盘点 阅读数314

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

比如说 李逵,在家称为"铁牛", 江湖上人称"黑旋风"
这两个称号都是他的

C++引用详解_f5
#include<iostream>
using namespace std;
int main()
{
	int a = 20;
	int& b = a;
	b = 20;
	return 0;
}

b是a的引用,也就是起了一个别名,a再取了一个名称

C++引用详解_赋值_02

同时改变别名b的值,也会改变a本身的值

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

1.错误举例

#include<iostream>
using namespace std;
int main()
{
	int a = 20;
	int& b;
	return 0;
}

若使用引用不初始化,b是谁的别名?

2.一个变量可以有多个别名

#include<iostream>
using namespace std;
int main()
{
	int a = 10;
	int& b = a;
	int& c = a;
	int& d = a;
	return 0;
}


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

C++引用详解_赋值_03

此时由于b与c的地址不同,说明并不是b作为c的别名
b值与c值相等,而是将c的值传给b

3.常引用

1.错误举例

#include<iostream>
using namespace std;
int main()
{
	const int a = 10;
	int& b = a;
	return 0;
}

const 修饰a后,a为只读,b是int型,所以为可读可写。
所以会报错

2.正确举例

#include<iostream>
using namespace std;
int main()
{
	const int a = 10;
	const int& b = a;
	return 0;
}

将b的类型修改为const int型 即可通过

3.权限问题

C++引用详解_f5_04

别名d 的权限从原来c的可读可写变成了只读,所以可以通过

总结:引用取别名时,变量访问权限可以缩小不能放大

4.引用误区

赋值与起别名是两回事

1.起别名

#include<iostream>
using namespace std;
int main()
{
	const int a = 1;
	 int& b = a;
	return 0;
}

C++引用详解_赋值_05

由于起别名是给自己再取一个名称,所以该别名的修改会影响到本身变量
所以就要求 别名的权限可以小于等于本身变量,但不能大于本身变量

#include<iostream>
using namespace std;
int main()
{
	const int a = 1;
	 int  b = a;
	return 0;
}

C++引用详解_#include_06

赋值不会改变a变量本身,自然就不用考虑权限大小的问题

5.使用场景

1.引用做参数

C++引用详解_#include_07

相当于 int &s1=a; int &s2=b;
s1是a的别名,s2是b的别名

2.引用做返回值

C++引用详解_赋值_08

为什么 r1不可以接收,而r2可以呢?

1.传值返回

C++引用详解_赋值_09

在count1中返回的实际上是一个临时变量 假设临时变量为tmp,开辟了一块空间
即 int tmp=n 即tmp为n的拷贝

2.传引用返回

C++引用详解_#include_10

在count2中,假设有一个临时变量tmp,但是该变量没有开辟空间,
因为tmp是作为n的别名,即tmp为n本身
int& tmp=n

C++引用详解_#include_11

在r1接收返回时,因为count1返回临时变量tmp具有常性,所以r1要用 const修饰
在r2接收返回时,因为返回的临时变量tmp为n本身,n为int型,所以可以正常返回

6.使用局部变量返回的危害

#include<iostream>
using namespace std; 
 int& add(int a, int b)
{
	int c = a + b;
	return c;
}
int main()
{
	int& ret = add(1, 2);
	add(3, 4);
	cout << ret << " " << endl;	
	return 0;
}

该程序执行完,结果是什么?
正常来说,ret=3,实际结果ret=7

C++引用详解_#include_12

c是局部变量,所以会随着函数的销毁而销毁,因为是引用返回,ret为c的别名
ret=3

C++引用详解_赋值_13

再次创建跟跟刚才同样大小的空间,c的值变化为7,由于ret为c的别名,所以ret=7

###1.解决方法

使用static引用返回

#include<iostream>
using namespace std; 
 int& add(int a, int b)
{
	static int c = a + b;
	return c;
}
int main()
{
	int& ret = add(1, 2);
	add(3, 4);
	cout << ret << " " << endl;	
	return 0;
}

ret=3

C++引用详解_f5_14

c此时处于静态区中,所以不会随着函数的销毁而销毁
引用返回,ret为c的别名,ret=3

C++引用详解_#include_15

因为static int c=a+b,只会定义一次
add(3,4) 中c值依旧为3
所以ret=3

2.测试用例

#include<iostream>
#include<time.h>
using namespace std;
struct A
{
int a[10000];
};
A a;
A test1()//值返回
{
return a;
}
A& test2()//引用返回
{
return a;
}
int main()
{
//以值作为函数的返回值类型
size_t begin1 = clock();
for (size_t i = 0; i < 1000000; i++)
{
test1();
}
size_t end1 = clock();
//以引用返回作为函数的返回值类型
size_t begin2 = clock();
for (size_t i = 0; i < 1000000; i++)
{
test2();
}
size_t end2 = clock();
//计算两个函数运算完成之后的时间
cout << "test1 time :" << end1 - begin1 << endl;
cout << "test2 time :" << end2 - begin2 << endl;

return 0;


C++引用详解_赋值_16

效率差距还是有的,引用返回,不需要创建空间来存储临时变量,
而值返回则需要创建空间来存储临时变量


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK