【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++中引用相关的一些学习记录总结,如有错误,希望大家帮忙指正,也欢迎大家给予建议和讨论,谢谢!

相关内容

热门资讯

感恩节英文作文【精选6篇】 感恩节英文作文 篇一Title: Thanksgiving Day - A Time for Gra...
要强的我作文350字【精选3... 要强的我作文350字 篇一我是一个要强的人,对于自己的要求总是很高,无论是学习还是生活。我相信只有要...
特殊的课堂 Special ... 特殊的课堂 Special classroom 篇一特殊的课堂 Special classroom ...
学习英语的争论高中英语作文【... 学习英语的争论高中英语作文 篇一标题:学习英语的重要性在当今的全球化时代,英语已经成为了一门全球通用...
大学的优秀英语作文带翻译【精... 大学的优秀英语作文带翻译 篇一:大学生应如何充分利用大学资源Title: How College S...
高职单招英语作文范文【经典6... 高职单招英语作文范文 篇一:实施高职单招的优势和挑战In recent years, vocatio...
友谊的英语名言【推荐4篇】 友谊的英语名言 篇一Friendship is a treasure that knows no b...
小学英语句子对话【优秀3篇】 小学英语句子对话 篇一Title: A Day at the ZooIntroduction:One...
英语优秀作文:人与自然(经典... 英语优秀作文:人与自然 篇一The Beauty and Fragility of NatureNa...
老师的英语作文 老师的英语作文15篇  在平平淡淡的日常中,大家都有写作文的经历,对作文很是熟悉吧,作文是通过文字来...
中国青年节英语作文 Chin... 中国青年节英语作文 Chinese Youth Day 篇一Chinese Youth Day is...
梦想的英语作文(最新6篇) 梦想的英语作文 篇一My DreamEveryone has dreams. Some dream ...
高中英语作文常用句型(推荐3... 高中英语作文常用句型 篇一常用句型在高中英语作文中扮演着非常重要的角色。它们不仅能够提高文章的语言表...
我的十年英语作文(精选4篇) 我的十年英语作文 篇一十年前,我刚刚开始接触英语。那时的我对于这门陌生的语言充满了好奇和期待。我记得...
英语作文范文大全150字【优... 英语作文范文大全150字 篇一Title: The Importance of Learning E...
六下英语好词及句子精选490... 六下英语好词及句子 精选69句1. It reveals the unquestionable fa...
爱心英语作文 爱心英语作文  在生活、工作和学习中,说到作文,大家肯定都不陌生吧,借助作文人们可以反映客观事物、表...
开展读书活动英语作文(优质6... 开展读书活动英语作文 篇一Title: The Importance of Book Reading...
外出旅游英语作文(精选3篇) 外出旅游英语作文 篇一Title: A Memorable Trip to the BeachInt...
健康饮食方面的英语作文(通用... 健康饮食方面的英语作文 篇一Title: The Importance of Healthy Eat...