📢博客主页:https://blog.csdn.net/2301_779549673
📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
📢本文由 JohnKi 原创,首发于 CSDN🙉
📢未来很长,值得我们全力奔赴更美好的生活✨
文章目录
- 📢前言
- 🏳️🌈引用的概念和定义
- ❤️引用的特性
- 🧡引用的属性和特别之处
- 👥总结
📢前言
C++新增了一种复合类型–引用变量
。引用是已定义的变量的别名(另一个名称)。例如,如果将twain作为clement变量的引用,则可以交替使用twain 和clement来表示该变量。那么,这种别名有何作用呢?是否能帮助那些不知道如何选择变量名的人呢?有可能,但引用变量的主要用途是用作函数的形参。通过将引用变量用作参数,函数将使用原始数据,而不是其副本。这样除指针之外,引用也为函数处理大型结构提供了一种非常方便的途径,同时对于设计类来说,引用也是必不可少的。然面,介绍如何将引用用于函数之前,先介绍一下定义和使用引用的基本知识。请记住,下述讨论旨在说明引用是如何工作的,而不是其典型用法。
先说说左右值
的概念
C++中所有值必然属于左值或者右值,
在C++11中可以取地址的、有名字的就是左值
反之,不能取地址的、没有名字的就是右值。
🏳️🌈引用的概念和定义
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间它和它引用的变量共用同一块内存空间。比如:水壶传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;
类型& 引用别名=引用对象;
#include<iostream>
using namespace std;
int main()
{
int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;
++d;
// 这⾥取地址我们看到是⼀样的
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl << endl;cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
return 0;
}
(1)可见,引用的定义方式类似于指针,只是用&取代了*。你可以这样理解:忽略&这个符号本身的意义,这里提出了一个新的概念"引用”,指针表示某个变量的地址,引用表示这个变量本身。
(2)引用必须在定义的同时初始化,并且以后也要从一而终,不能再引用其它数据,有点类似于 const 变量,
❤️引用的特性
- 引用在定义时必须初始化
- 一个变量可以有多个引用
- 引用一旦引用一个实体,再不能引用其他实体
#include<iostream>
using namespace std;
int main()
{int a = 10;// 编译报错:“ra”: 必须初始化引⽤//int& ra;int& b = a;int c = 20;// 这⾥并⾮让b引⽤c,因为C++引⽤不能改变指向,// 这⾥是⼀个赋值b = c;cout << &a << endl;cout << &b << endl;cout << &c << endl;return 0;
}
引用更接近 const
指针,必须再创建时进行初始化,一旦与某个变量联系起来,就将一直效忠于它,也就是说
int& rondents = rats;
实际上就是下述代码的伪装
int* const pr = &rats;
其中,引用rondents
扮演的角色与表达式*pr
相同
🧡引用的属性和特别之处
我们有意编写一个奇怪的立方计算代码
double cube(double a);
double refcube(double& ra);
int main() {using namespace std;double x = 3.0;cout << cube(x);cout << " = cube of " << x << endl;cout << refcube(x);cout << " = refcube of " << x << endl; return 0;
}
double cube(double a)
{a *= a * a;return a;
}double refcube(double& ra)
{ra *= ra * ra;return ra;
}
下面是该程序的输出结果
refcube()
函数修改了 main( )中的x值,而 cube()
没有,这提醒我们为何通常按值传递。变量a位于cube()中,它被初始化为x的值,但修改a并不会影响x。但由于refcube()使用了引用参数,因此修改ra实际上就是修改x。如果程序员的意图是让函数使用传递给它的信息,而不对这些信息进行修改,同时又想使用引用,则应使用常量引用。
例如,在这个例子中,应在函数原型和函数头中使用const:
double refcube(const double &ra);
如果这样做,当编译器发现代码修改了ra的值时,将生成错误消息。
顺便说一句,如果要编写类似于上述示例的函数(即使用基本数值类型),应采用按值传递的方式,而不要采用按引用传递的方式。当数据比较大(如结构和类)时,引用参数将很有用。
按值传递的函数,可使用多种类型的实参,例如,下面的调用都是合法的
double z = cube(x + 2.0);
z = cube(8.0);
int k = 10;
z = cube(k);
double yo[3] = (2.2, 3.3, 4.4, 5.5);
z = cube(yo[2])
如果将与上面类似的参数传递给接受引用参数的函数,将会发现,传递引用的限制更严格。毕竟,如果ra是一个变量的别名,则实参应是该变量
例如,下面的代码不合理,因为表达式x+3.0并不是变量
double z=refcube(x+3,0):
所以如果实参与引用参数不匹配,C++将生成临时变量。当前,仅当参数为const引用时,C++才允许样做,但以前不是这样。下面来看看何种情况下,C++将生成临时变量,以及为何对const 引用的限制合理的。
首先,什么时候将创建临时变量呢?如果引用参数是const,则编译器将在下面两种情况下生成变量:
- 实参的类型正确,但不是左值;
- 实参的类型不正确,但可以转换为正确的类型。
在C语言中,左值最初指的是可出现在赋值语句左边的实体,但这是引入关键字const之前触况。现在,常规变量和const变量都可视为左值,因为可通过地址访问它们。但常规变量属于可修改的值,而const 变量属于不可修改的左值。
回到前面的示例。假设重新定义了refcube()
,使其接受一个常量引用参数:
double refcube(const double& ra);
int main() {using namespace std;double x = 3.0;double side = 3.0; double* pd = &side; double& rd = side; long edge = 5L; double lens[4] = { 2.0, 5.0, 10.0, 12.0 };double c1 = refcube(side); double c2 = refcube(lens[2]);double c3 = refcube(rd);double c4 = refcube(*pd);double c5 = refcube(edge); double c6 = refcube(7.0); double c7 = refcube(side + 10.0);return 0;
}
double refcube(const double &ra)
{return ra * ra * ra;
}
下面是该程序的输出结果
👥总结
本篇博文对 引用变量 做了一个较为详细的介绍,不知道对你有没有帮助呢
觉得博主写得还不错的三连支持下吧!会继续努力的~