【C++】C++引用(上)

简介: 【C++】C++引用(上)

1. 引用的概念


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

使用规则:类型& 别名 = 引用实体


举个栗子:

5b83b598e2aa0ff49eb33ce58907afbb.png

图一

我们发现,对于变量a,我们用ra当作他的别名,然后我们又定义了一个引用变量x,他的引用实体是ra,这说明了同一变量,可以有多个引用。然后我们注意右边的调试窗口,可以发现a,ra,x,y的地址都是相同的,所以他们共用同一块内存空间。


那么,我们要怎么使用呢?举个栗子,我们之前学习C语言的时候写过一个Swap函数

void swap(int* x, int* y)
{
  int tmp = *x;
  *x = *y;
  *y = tmp;
}


这里需要传地址给Swap函数,才能实现交换变量值的功能,但是如果使用引用,就可以省略解引用的操作。

void Swap(int& x, int& y)
{
  int tmp = x;
  x = y;
  y = tmp;
}

注意:引用类型必须和引用实体是同种类型的,否则会报错,在VS2022环境下报如下错误:error C2440: “初始化”: 无法从“int”转换为“char &”


2. 引用的特性


  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体


对于特性1:

88df3d23d50cd4abea0366df2e3ccae0.png

图二

对于特性二:在图一中已经很好的体现出来。


对于特性三:假设我们想改变引用的实体,我们应该会使用类似与“ra = b”这种语句,但是如下图,我们看到第31行代码并没有报错,那么是不是表示引用变量引用的实体是可以改变的呢?注意右边的监视窗口,ra的地址和b的地址并不相同,这说明ra不是b的引用,ra还是a的引用,所以第31行的语句是改变a的值,而不是改变ra的引用。

de7b66461571371b6828729117605895.png

图三


3. 常引用


常引用就是在定义引用变量时加上const修饰。

我们看下面一段代码

void TestConstRef()
{
  const int a = 10;
  int& ra = a;
  const int& ra = a;
  int& b = 10;
  const int& b = 10;
  double d = 12.34;
  int& rd = d;
  const int& rd = d;
}


这段代码有什么问题呢?

bc31bec1646788168eb26ac57b1db657.png

图四

运行之后发现,第40行因为我们定义的变量a是用const修饰的,而ra是没有用const修饰的,是可以更改的,这样的话,引用变量的权限还变大了,这是不合理的。第41行中,ra的类型和a的类型相同,都是const int类型,所以不会报错。对于第42行,变量b引用的是一个常量,是不可修改的,但是b本身的权限是可修改的,也造成了权限的扩大,所以报错。后面的第45行也是同理,因此我们得出结论:指针和引用赋值中,权限可以缩小,可以平移,但是不能扩大。

那么,常引用有什么使用场景呢?我们看下面一个例子

void Func(int& x)//假设传一个参数
{
  //做一些不需要修改传入的值的操作
  //...
}
int main()
{
  int a = 10;
  int& ra = a;
  const int& rra = ra;
  Func(a);
  Func(ra);
  Func(rra);//const修饰的参数,传参的时候会出现权限放大的问题
  return 0;
}


对于这种情况,我们传一个const修饰的参数,就会出现问题,因此,在这个地方我们定义函数时应该使用"const int& x"来代替"int& x"。

const引用还有一个点需要注意,我们看下面一段代码

int main()
{
  const int& b = 10;
  double d = 12.34;
  int i = d;// 这句代码有问题吗?
  int& ri = d;// 这句代码有问题吗?
  return 0;
}


答案是第一句没有问题,第二句有问题。为什么呢?因为在第二句中,ri的类型时int&,但是d的类型是double,所以在指定引用实体的时候,指定的并不是d的空间,即ri并不是d的别名,而是在转换之前开辟了一块临时变量存储int类型的数据,这个数据是d中存放的值转换而来的,而语法规定:临时变量具有常性,可以理解为用const修饰过,所以这句代码就造成了权限扩大,所以这句代码我们应该改为"const int& ri = d"


注意:强转,截断,提升都会产生临时变量。


4. 使用场景


做参数


1. 输出型参数

f0f2b2c7d30df9fc88d743efc6696237.png

图五

2. 普通参数

16052167a5384322216a24391975982d.png

图六

相关文章
|
6月前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
94 1
|
7月前
|
C++
C++中的const指针与const引用
C++中的const指针与const引用
106 2
|
5月前
|
存储 安全 C++
浅析C++的指针与引用
虽然指针和引用在C++中都用于间接数据访问,但它们各自拥有独特的特性和应用场景。选择使用指针还是引用,主要取决于程序的具体需求,如是否需要动态内存管理,是否希望变量可以重新指向其他对象等。理解这二者的区别,将有助于开发高效、安全的C++程序。
41 3
|
5月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
6月前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
71 5
|
6月前
|
C++
C++引用
C++引用
|
6月前
|
存储 安全 编译器
【C++入门】—— C++入门 (中)_引用
【C++入门】—— C++入门 (中)_引用
42 5
|
6月前
|
C语言 C++ 编译器
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
|
6月前
|
安全 测试技术 C++
C++中的引用
C++中的引用
38 1