【C++入门】引用详解(引用的特性、引用的使用、引用与指针的区别)
创始人
2024-05-23 14:24:06
0

文章目录

  • 1 引用概念
  • 2 引用特性
  • 3 使用场景
  • 4 常引用
  • 5 传值与传引用的效率比较
    • 5.1 值和引用作为函数参数的性能比较
    • 5.2 值和引用作为返回值类型的性能比较
  • 6 引用和指针的区别


1 引用概念

引用不是新定义一个变量,而是给已存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用一块内存空间。
格式:引用类型& 引用变量名(对象名) = 引用实体;
注意: 引用类型和引用实体是同种类型的。

引用示例:

引用示例图


2 引用特性

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

  2. 一个变量可以有多个引用,也可以对引用再进行引用(或者说可以为变量取多个别名,也可以为别名再取别名)
    示例:
    引用示例

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

示例


3 使用场景

  1. 引用做参数
void Swap(int& num1, int& num2)
{int temp = num1;num1 = num2;num2 = temp;
}

示例

  1. 引用做返回值

前言:传值返回

  • 当用值作为返回值时,不是直接将变量返回,而是返回变量的一份临时拷贝(临时变量)。考虑到对于函数中的局部变量,在调用完函数时即被销毁,此时需要返回的变量也会被销毁(空间不再属于该变量),因此选择在销毁前将变量值拷贝到一个临时变量中(这个临时变量一般由寄存器(4/8个字节大小)充当,如eax;如果返回值过大,则会选择在上层栈帧中创建临时变量),再将临时变量作为返回值返回。
    示例

  • 那如果作为返回值的变量出作用域后不会被销毁,那还会产生临时变量吗?事实上,编译器不管需要返回的变量出作用域后会不会被销毁,在返回时都会产生临时变量。
    示例

传引用返回

  • 那既然需要返回的变量都不会被销毁,将其再拷贝到临时变量中是不是麻烦了些?因此,在下面我们以引用作为返回值,但这不是说就不会创建临时变量了,临时变量依然会被创建,但这个临时变量相当于返回变量的一个别名,因为该变量出作用域后不会被销毁,因此我们依然可以进行访问,此时临时变量与返回变量共用一块空间,相比于传值返回,中间就减少了拷贝的过程,返回时同样将临时变量赋值给接收的变量即可,可以认为传引用返回就相当于将变量直接返回了。
    示例


    下面再看一段示例代码:
int& Add(int a, int b)
{int c = a + b;return c;
}int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :" << ret << endl;return 0;
}

示例输出结果:
示例

说明:对于以出了作用域即被销毁的变量作为返回值的,如果使用传引用返回实际上是无意义的,因为局部变量的空间已被销毁,不再属于该变量,再通过传引用返回的别名去访问该空间时,其值是不确定的,无法确保得到的还是正确结果。

引用做返回值示例

注意:如果函数返回时,出了函数作用域,如果返回对象还在(空间还没还给系统,如:静态变量、全局变量、上一层栈帧中的变量、malloc开辟的等等),则可以使用引用返回,否则,必须使用传值返回。

  • 传引用返回还可修改返回值。

    示例代码:
#define N 10
typedef struct Array {int a[N];int size;
}AY;//查找数组中某个下标位置的元素
int& PosAt(AY& ay, int i) {assert(i < N);//保证不越界return ay.a[i];
}int main() {AY ay;for (int i = 0; i < N; i++) {PosAt(ay, i) = i * 10;//用返回的别名进行修改}for (int i = 0; i < N; i++) {cout << PosAt(ay, i) << " ";}cout << endl;return 0;
}

示例输出结果:
示例


4 常引用

指针和引用,在赋值和初始化时,权限可以保持或缩小,但不能放大。

示例代码:

//传值返回
int Count() {int n = 0;n++;return n;
}void TestConstRef() {//示例1const int a = 10;//const修饰的变量,具有常属性,不可修改//错误语法,权限被放大。ra引用与a共用一块空间,而a具有常属性,//如果ra引用不具有常属性,则修改ra的值时则违背了a的常属性//int& ra = a;//编译时会报错const int& ra = a;//正确语法//示例2//int& b = 10;//错误语法,10为常量,引用权限放大const int& b = 10;//正确语法,使引用变量b也具有常属性//示例3//Count函数是传值返回的,返回的是临时变量,临时变量具有常属性//int& ret = Count();//编译报错const int& ret = Count();//正确语法,ret为返回的临时变量的常引用int ret2 = Count();//正确语法,将返回的临时变量赋值给ret2//示例4double d = 3.14;//int& rd = d;//编译报错,引用类型与引用实体不是同一种类型//解释://在进行类型转换(无论是强制类型转换还是自动类型提升)时都会产生临时变量//如有int i = 0; (double)i:其并不是直接将int型变量i转换为double型,//而是通过一个临时变量将i转化为double,如果是double d = i;则是再将临时变量赋值给d//下句代码则表示rd为double型变量d强制转换为int型变量时产生的 临时变量 的常引用//但注意,rd本质上并不是d的引用,二者也不是共用一个空间//d仍是double型变量,rd则为int型const int& rd = d;//编译通过printf("d = %f\nrd = %d\nd的地址为:%p\nrd的地址为:%p\n", d, rd, &d, &rd);
}int main() {TestConstRef();return 0;
}

示例


5 传值与传引用的效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时拷贝,因此用值作为参数或返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低了。

下面用两段测试代码来比较传值与传引用的效率:

5.1 值和引用作为函数参数的性能比较

测试代码:

#include using namespace std;#include 
struct A { int a[100000]; };
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}int main() {TestRefAndValue();return 0;
}

测试结果:

性能比较结果
分析:从测试结果来看,值作为参数的函数运行时间要比引用作为参数的函数运行时间多得多,以引用作为参数能很好提升程序运行效率。


5.2 值和引用作为返回值类型的性能比较

测试代码:

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

测试结果:

测试结果
分析:从测试结果来看,值作为返回值类型的函数运行时间要比引用作为返回值类型的函数运行时间多得多,以引用作为返回值类型能很好提升程序运行效率。


6 引用和指针的区别

  • 语法概念上 引用就是一个别名,没有独立空间,和其引用实体共用一块空间。而指针是有开辟独立空间的,空间中存放的是指向的变量的空间地址。

    示例代码:
int main()
{int a = 10;int& ra = a;//引用aint* pa = &a;//指向acout << "&a = " << &a << endl;cout << "&ra = " << &ra << endl;cout << "&pa = " << &pa << endl;return 0;
}

示例输出结果:

示例结果

  • 引用在 底层实现上 实际是有空间的,因为引用是按照指针方式来实现的。

    示例代码:
int main()
{int a = 10;int& ra = a;ra = 20;int* pa = &a;*pa = 20;return 0;
}

进入调试,通过反汇编,查看引用和指针的汇编代码,对比发现:**在汇编代码中,引用和指针的实现相同,都是开辟了独立的空间,将指向变量的地址赋值给了引用变量或指针变量。**

反汇编示例


🍚引用和指针的不同点:

  1. 引用在概念上是定义一个变量的别名,指针则是存储一个变量的地址。
  2. 引用在定义时必须初始化,指针则没有要求。
  3. 引用在初始化时引用一个实体后,就不能再引用其它实体,而指针可以在任何时候指向任何一个同类型实体。
  4. 没有NULL引用,但有NULL指针。
  5. sizeof 中的含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)。
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个所指向实体类型的大小。
  7. 有多级指针,但没有多级引用。
  8. 访问实体方式不同,指针需要显示解引用,引用是由编译器自己处理。
  9. 引用比指针使用起来相对安全。不会有类似空指针等的问题。

以上是我对C++中引用相关的一些学习记录总结,如有错误,希望大家帮忙指正,也欢迎大家给予建议和讨论,谢谢!

相关内容

热门资讯

斗篷山导游词最新 斗篷山导游词最新范文  作为一位不辞辛劳的导游,就不得不需要编写导游词,导游词是讲解当地的基本情况,...
云南省大理概况导游词 云南省大理概况导游词(精选5篇)  作为一无名无私奉献的导游,通常会被要求编写导游词,导游词是导游员...
武当山南岩宫导游词 武当山南岩宫导游词(精选12篇)  作为一名可信赖的导游人员,常常需要准备导游词,导游词具有极强的实...
合肥包公园导游词 合肥包公园导游词  包公园,位于安徽省合肥市芜湖路72号,始建于北宋嘉祐七年,是为纪念北宋著名清官包...
景点贵阳花溪公园导游词 景点贵阳花溪公园导游词  作为一位兢兢业业的旅游从业人员,时常需要用到导游词,借助导游词可以更好地宣...
孔庙导游词   孔庙导游词(一)  尊敬的各位来宾:  你们好!我受旅游、接待部门的委托,对光临名城曲阜参观游览...
石家庄驼梁景区导游词 石家庄驼梁景区导游词尊敬的各位游客:  大家好!  欢迎大家来到驼梁,我是中游旅行社的一名导游员,我...
介绍傣家竹楼导游词300 傣家竹楼是傣族固有的典型建筑。下层高约七八尺,四无遮栏,牛马拴束于柱上。上层近梯处有一露台,转进为长...
电视剧《乱世佳人》简介及经典... 电视剧《乱世佳人》简介及经典台词  电视剧简介:  《乱世佳人》亦可称为民国版《美人心计》,由唐嫣饰...
丹东鸭绿江导游词 丹东鸭绿江导游词  鸭绿江是我们中国和朝鲜的分界线,各位导游,请看下面的丹东鸭绿江导游词,希望可以帮...
幼儿园运动会闭幕式主持词 幼儿园运动会闭幕式主持词  主持人在台上表演的灵魂就表现在主持词中。随着社会一步步向前发展,各种场合...
70大寿主持词 70大寿主持词  主持词的写作需要将主题贯穿于所有节目之中。现今社会在不断向前发展,主持人的需求越来...
个人领奖感谢词 个人领奖感谢词(精选7篇)  获得奖励或者嘉奖,不仅是一份荣誉,更是一份激励。你知道怎么写感谢词吗,...
重阳节经典致辞 关于重阳节经典致辞(精选6篇)  在生活、工作和学习中,大家都不可避免地会接触到致辞吧,致辞要求风格...
幼儿园元旦文艺汇演主持词 男小主持:尊敬的家长,亲爱的老师女小主持:可爱的小朋友合:大家新年好!男小主持:春夏秋冬,黑夜清晨女...
大话西游降妖篇2台词 大话西游降妖篇2台词  导语:《西游伏妖篇》也是继春节档周星驰执导电影《美人鱼》中徐克客串表演之后,...
晚会活动主持词   引导语:晚会最重要的一点就是主持,而有关晚会活动的主持词要怎么写呢?接下来是小编为你带来收集整理...
周年庆活动主持词 周年庆活动主持词9篇  借鉴诗词和散文诗是主持词的一种写作手法。在人们越来越多的参与各种活动的今天,...
《手机》经典台词 《手机》经典台词  砖头媳妇:装得跟头会想事的猪一样。  于文娟:老费吃了不管用,说明他不是不能,而...
公司工会代表大会主持词 公司工会代表大会主持词  各位代表:  请大家坐好,会议马上就要开始了,公司工会代表大会主持词。(待...