【深入理解C++】引用

1.变量的别名

在 C 语言中,使用指针(Pointer)可以间接获取、修改某个变量的值。在 C++ 中,使用引用(Reference)可以起到跟指针类似的功能。

引用相当于是变量的别名,一般用 & 符号表示,基本数据类型、枚举、结构体、类、指针、数组等都可以有引用。

引用必须绑定到变量上去,不能绑定到常量上去。引用指向的类型要相同。

对引用做计算,就是对引用所指向的变量做计算。

在定义的时候就必须初始化,一旦指向了某个变量,就不可以再改变,“从一而终”。

#include <iostream>
using namespace std;

int main() {
	int age = 10;
	int height = 20;

	// 定义了一个age的引用,ref相当于是age的别名
	int &ref = age;
	ref = 20;
	ref += 30;
	cout << age << endl; // 50

	ref = height;
	ref = 11;
	cout << age << endl; // 11
	cout << height << endl; // 20
	
	return 0;
}

2.变量的多个别名

可以利用引用初始化另一个引用,相当于某个变量的多个别名。

#include <iostream>
using namespace std;

int main() {
	int age = 10;

	// 定义了一个age的引用,ref相当于是age的别名
	int& ref = age;
	int& ref1 = ref;
	int& ref2 = ref1;

	ref += 10;
	ref1 += 10;
	ref2 += 10;

	cout << age << endl; // 40
	
	return 0;
}

3.引用存在的价值

不存在 “引用的引用”、“指向引用的指针”、“引用数组”。

引用存在的价值之一:比指针更安全、函数返回值可以被赋值。

举例1:通过指针传参交换两个数

#include <iostream>
using namespace std;

void swap(int *v1, int *v2) {
	int tmp = *v1;
	*v1 = *v2;
	*v2 = tmp;
}

int main() {
	int a = 10;
	int b = 20;
	swap(&a, &b);
	cout << "a = " << a << ", b = " << b << endl; // a = 20, b = 10

	return 0;
}

举例2:通过引用传参交换两个数

#include <iostream>
using namespace std;

void swap(int &v1, int &v2) {
	int tmp = v1;
	v1 = v2;
	v2 = tmp;
}

int main() {
	int a = 10;
	int b = 20;
	swap(a, b);
	cout << "a = " << a << ", b = " << b << endl; // a = 20, b = 10

	int c = 2;
	int d = 3;
	swap(c, d);
	cout << "c = " << c << ", d = " << d << endl; // c = 3, d = 2

	return 0;
}

4.引用的大小

一个引用占用一个指针的大小。

举例1:只含一个 int 整数的类对象的大小

#include <iostream>
using namespace std;

struct Student {
	int age;
};

int main() {
	cout << sizeof(Student) << endl;
	// x64(64bit): 4
	// x86(32bit): 4

	return 0;
}

举例2:只含一个 int 指针的类对象的大小

#include <iostream>
using namespace std;

struct Student {
	int *age;
};

int main() {
	cout << sizeof(Student) << endl;
	// x64(64bit): 8
	// x86(32bit): 4

	return 0;
}

举例3:只含一个 int 引用的类对象的大小

#include <iostream>
using namespace std;

struct Student {
	int &age;
};

int main() {
	cout << sizeof(Student) << endl;
	// x64(64bit): 8
	// x86(32bit): 4

	return 0;
}

5.从汇编角度看引用

引用的本质就是指针,只是编译器削弱了它的功能,所以引用就是弱化了的指针。

加断点,按 F5 进入调试,转到反汇编,不勾选“显示符号名”。

举例1:查看 int 指针的汇编代码

#include <iostream>
using namespace std;

int main() {
	
	int age = 10;

	// *p就是age的别名
	int *p = &age;
	*p = 30;

	return 0;
}

在这里插入图片描述

举例2:查看 int 引用的汇编代码

#include <iostream>
using namespace std;

int main() {
	
	int age = 10;

	// ref就是age的别名
	int &ref = age;
	ref = 30;

	return 0;
}

在这里插入图片描述

对比两图可以发现,ref 本质上就是指针,存储的就是 age 的地址值。

6.结构体的引用

#include <iostream>
using namespace std;

struct Date {
	int year;
	int month;
	int day;
};

int main() {

	Date d = { 2022, 1, 25 };
	Date& ref = d;
	ref.year = 2023;

	cout << d.year << endl; // 2023

	return 0;
}

7.指针的引用

指针是一个存放地址的变量,而指针引用指的是这个指针变量的引用。

#include <iostream>
using namespace std;

int main() {

	int age = 10;

	int *p = &age;
	int *&ref = p;
	*ref = 30;
	cout << age << endl; // 30

	int height = 40;
	ref = &height;
	cout << *ref << endl; // 40

	return 0;
}

在 C++ 中,如果参数不是引用的话,会调用参数对象的拷贝构造函数,所以如果想改变指针所指的对象(即想要改变指针里面存的地址),就要使用指针引用。

举例1:指针

#include <iostream>
using namespace std;

struct Point
{
    int x;
    int y;
};

void change1(Point* pp)
{
    pp = new Point;
    pp->x = 4;
}

int main()
{
    Point* p = new Point;
    p->x = 10;
    cout << "指针前:" << p->x << endl;
    change1(p);
    cout << "指针后:" << p->x << endl;

    return 0;
}

在这里插入图片描述

举例2:指针的引用

#include <iostream>
using namespace std;

struct Point
{
    int x;
    int y;
};

void change2(Point* &pp)
{
    pp = new Point;
    pp->x = 4;
}

int main()
{
    Point* p = new Point;
    p->x = 10;
    cout << "指针引用前:" << p->x << endl;
    change2(p);
    cout << "指针引用后:" << p->x << endl;

    return 0;
}

在这里插入图片描述

8.数组的引用

举例1:区分指针数组、数组指针、数组的引用

#include <iostream>
using namespace std;

int main() {

	int array[3] = {1, 2, 3};

	// 指针数组,数组里面可以存放3个int*
	int *arr1[3] = {array, array, array};
	
	// 数组指针,用于指向数组的指针
	int (*arr2)[3] = &array;

	// 数组的引用
	int (&ref)[3] = array;
	ref[0] = 10;
	cout << array[0] << endl; // 10

	return 0;
}

举例2:引用数组的两种格式

#include <iostream>
using namespace std;

int main() {

	// 数组名arr其实是数组的地址,也是数组首元素的地址
	// 数组名arr可以看做是指向数组首元素的指针(int *)
	int arr[] = {1, 2, 3};

	cout << *(arr + 2) << endl; // 3
	// 等价于arr[2]
	
	// 数组的引用格式1
	int (&ref)[3] = arr;
	cout << ref[2] << endl; // 3

	// 数组的引用格式2
	int * const &refArr = arr;
	cout << refArr[2] << endl; // 3

	return 0;
}
  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值