当前位置: 首页 > 工具软件 > reference > 使用案例 >

C++的引用(Reference)

羿博延
2023-12-01

十、C++的引用(Reference)

1、定义
1)引用就是某个变量的别名,对引用的操作与对变量操作完全相同。
2)语法:
类型 &引用名 = 变量名;
注:a、引用在定义时必须要初始化,初始化以后绑定的变量的不能再修改。 int &b;//error
b、引用的类型与初始化时绑定的变量类型要一致。
eg:
int a = 123;
int &b = a;//b就是a的引用(别名)
b++;
cout << a << endl;//124

int c = 321;
b = c;//将c的值赋值给b,等价赋值给a
cout << a << endl;//321

09reference.cpp

#include <iostream>
using namespace std;

int main(void){
	int a = 10;
	int &b = a;//b引用a,b就是a的别名
	cout << "&a=" << &a << ",a=" << a << endl;
	cout << "&b=" << &b << ",b=" << b << endl;

	b++;
	cout << "a=" << a << endl;//11
	cout << "b=" << b << endl;//11
	a++;
	cout << "a=" << a << endl;//12
	cout << "b=" << b << endl;//12
	
	//引用定义时必须初始化
	//int &r;//error(不初始化)

	int c = 66;
	b = c;//将c赋值给b(a), 而不是修改引用目标
	cout << "a=" << a << endl;//66
	cout << "b=" << b << endl;//66

	//引用类型和绑定的目标类型要一致
	//double &d = c;//error
	
	return 0;
}

2、常引用
1)定义引用时加const修饰,即为常引用,不能通过常引用修改引用的目标。
const 类型 &引用名 = 变量名;
类型 const &引用名 = 变量名;
这两种语法的作用是一样的。
eg:
int a = 1000;
const int *pa = &a;
int const *pa = &a;

int a = 0;
const int &b = a;//b就是a的常引用
b++;//error
a = 100;
cout << b << endl;//100

2)普通引用只能引用左值,而常引用也叫万能引用,既能引用左值也能引用右值。

int a = 100;
int &b = a;//ok
int &b = 100;//error

const int &b = a;//ok
const int &b = 100;//ok

3)关于左值和右值
左值:可以放在赋值运算符(=)左侧,一般普通的变量都是左值
–》普通变量
–》赋值表达式结果
–》前++、–表达式

右值:只能放在赋值运算符(=)右值,一般常量都是右值
–》常量
–》大多数的表达式结果
–》函数返回临时变量(将亡右值)

constRef.cpp

#include <iostream>
using namespace std;

int main(void){
	//普通引用不能引用右值
	//int &r = 100;//error
	
	//常引用既可以引用左值也可以引用右值
	const int &r = 100;//ok
	cout << r << endl;//100
	return 0;
}

3、引用型函数参数
1)将引用用于函数的参数,这时形参就是实参的别名,可以通过形参直接修改实参的值,同时避免数值传递过程,减小函数调用开销。(02refArg.cpp)
2)引用型参数有可能意外修改实参的值,如果不希望修改实参本身,可以将形参定义为常引用,提高传参效率的同时还可以接收常量型的实参。(03refArg.cpp)

02refArg.cpp
#include
using namespace std;

void swap1(int *x, int *y){
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}

void swap2(int &x, int &y){
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
int main(void){
int a = 3, b = 5;
cout << “a=” << a << “,b=” << endl;
//swap1(&a, &b);
sesp2(a, b);
cout << “a=” << a << “,b=” << endl;
return 0;
}

03refArg.cpp
#include
using namespace std;

struct Student{
char name[128];
int age;
};
void print(const Student &s){//加const关键字可以防止函数修改引用目标
cout << s.name << ‘,’ << s.age << endl;
}
int main(void){
Student student = {“zhang”, 28};
print(student);//zhang,28
return 0;
}

4、引用型函数返回值
1)可以将函数的返回值声明为引用,避免返回值所带来的内存开销。
2)一个函数返回类型被声明为普通引用,那么函数返回值是一个左值。
3)如果不希望函数返回值直接返回左值,可以返回一个常引用。(const)
注:不要从函数中返回局部变量的引用,因为所引用的变量内存会在函数返回以后被释放,
但是可以返回成员变量、静态变量、全局变量的引用。

eg:
int func(void){
static int a = 100;
return a;//int tmp = a;实际返回结果是tmp
}
----------------------------------------------
int &func(void){
static int a = 100;
return a;//没有tmp,实际返回的就是a的自身
}

04refReturn.cpp
#include
using namespace std;

struct A{
int data;
/const/ int &func(void){
return data;
}

//不能返回局部变量的引用
/*
int &foo(void){
	int a = 123;
	return a;
}
*/

};
int main(void){
A a = {100};
a.func() = 200;//ok
cout << a.data << endl;//200
return 0;
}

5、引用和指针
1)如果从C角度去看引用,其本质就是指针,但是再C++中建议是使用引用而不是指针。
eg:
int a = 100;
int &ra = a;
int *const pa = &a;
*pa <=等价=> ra

2)指针可以不做初始化。其目标可以随意改变(指针常量除外);而引用必须初始化,而
且其引用目标不能再改变。
eg:
int a = 100, b =200;
int *p;//ok, 指针可以不做初始化
p = &a;//p指向a
p = &b; //p指向b
======================
int &r;//error
int &r = a;//引用定义必须初始化
r = b;//ok, 但是赋值操作,不是改变引用的目标

//后面区别了解
3)可以定义指针的指针(二级指针), 但不能定义引用的指针。
eg:
int a = 100;
int *p = &a;
int **pp = &p;//二级指针
================
int &r = a;
int &*pr = &r;//error

int *pr = &r;//pr不叫引用指针,就是一个普通指针

4)可以定义指针的引用,但不能定义引用的引用。
eg:
int a = 100;
int *p = &a;
int *&rp = p;//ok,指针的引用
=======================
int &r = a;
int &&rr = r;//error

int &rr = r;//ok,不能叫引用的引用,就是一个普通的引用,等于给a起了另一个别名

5)可以定义指针数组,但是不能定义引用数组
eg:
int a =10, b = 20, c = 30;
int *parr[3] = {&a, &b, &c};//ok,指针数组
int &rarr[3] = {a,b,c};//error

6)可以定义数组引用(给数组起别名)
eg:
int arr[3] = {10, 20, 30};
int (&rarr)[30] = arr;//ok,arr的别名

7)和函数指针类似,也可以定义函数引用(给函数起别名),其语法规则和函数指针类似。
eg:
void func(int a, int b){…}
int main(void){
void (*pfunc)(int int) = func;//函数指针
pfunc(10, 20);
==========================
void (&rfunc)(int, int) ]= func;//函数引用
rfunc(10, 20);
}

 类似资料: