C++引用使用总结

C++引用

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。引用是指针的另一种表示方式。

引用与指针区别:

引用很容易与指针混淆,它们之间有三个主要的不同:

  • 引用不能为空。
  • 引用指定过后不能修改。
  • 引用必须在创建时初始化。

基本用法

Type& ref = val;

案例:

#include <iostream>
using namespace std;

int main ()
{
    // 声明简单的变量
    double d;

    // 声明引用变量
    // 相当于给变量取一个别名
    double& s = d;

    // 操作引用就相当于操作本身
    s = 11.7;
    cout << "Value of d : " << d << endl;
    cout << "Value of d reference : " << s  << endl;

    // 一个变量可以有多个别名
    double& y = d;
    cout << "Value of other reference : " << y  << endl;

    // 引用的地址都相同
    cout << "d:" << &d << endl;
    cout << "s:" << &s << endl;
    cout << "y:" << &y << endl;

    return 0;
}

执行结果

Value of d : 11.7
Value of d reference : 11.7
Value of other reference : 11.7
------------
d:0x7ffc8cd21468
s:0x7ffc8cd21468
y:0x7ffc8cd21468

引用注意事项

#include <iostream>
using namespace std;

int main ()
{
    //1. 引用必须初始化
    //int& ref; //报错:必须初始化引用
    
    //2. 引用一旦初始化,不能改变引用
    int a = 10;
    int b = 20;
    int& ref = a;
    ref = b; //不能改变引用
    // ref = b; 作用等价于 a = b;
    
    //3. 不能直接对数组建立引用
    int arr[10];
    //int& ref2[10] = arr;
    return 0;
}

数组中的引用

//1. 建立数组引用方法一
//   通过 typedef 定义类型来使用引用
typedef int ArrRef[10];
int arr[10];
ArrRef& aRef = arr;
for (int i = 0; i < 10;i ++){
    aRef[i] = i+1;
}
for (int i = 0; i < 10;i++){
    cout << arr[i] << " ";
}
cout << endl;

//2. 建立数组引用方法二
int(&f)[10] = arr;
for (int i = 0; i < 10; i++){
    f[i] = i+10;
}
for (int i = 0; i < 10; i++){
    cout << arr[i] << " ";
}
cout << endl;

执行结果:

1 2 3 4 5 6 7 8 9 10 
10 11 12 13 14 15 16 17 18 19 

函数中的引用

**最常见看见引用的地方是在函数参数和返回值中。**当引用被用作函数参数的时,在函数内对任何引用的修改,将对函数外的参数产生改变。当然,可以通过传递一个指针来做相同的事情,但引用具有更清晰的语法。

如果从函数中返回一个引用,必须像从函数中返回一个指针一样对待。当函数返回值时,引用关联的内存一定要存在。

引用在函数参数中的使用

//值传递
void ValueSwap(int m,int n){
	int temp = m;
	m = n;
	n = temp;
}
//地址传递
void PointerSwap(int* m,int* n){
	int temp = *m;
	*m = *n;
	*n = temp;
}
//引用传递
void ReferenceSwap(int& m,int& n){
	int temp = m;
	m = n;
	n = temp;
}
void test(){
	int a = 10;
	int b = 20;
	//值传递 没有交换效果
	ValueSwap(a, b);
	cout << "a:" << a << " b:" << b << endl;
	//地址传递
	PointerSwap(&a, &b);
	cout << "a:" << a << " b:" << b << endl;
	//引用传递
	ReferenceSwap(a, b);
	cout << "a:" << a << " b:" << b << endl;
}

执行结果

a:10 b:20
a:20 b:10
a:10 b:20

引用的语法更清楚简单:

  • 函数调用时传递的实参不必加&
  • 在被调函数中不必在参数前加*

引用作为其它变量的别名而存在,因此在一些场合可以代替指针。C++主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。

引用在函数返回值中的使用

//返回局部变量引用
int& TestFun01(){
	int a = 10; //局部变量
	return a;
}
//返回静态变量引用
int& TestFunc02(){	
	static int a = 20;
	cout << "static int a : " << a << endl;
	return a;
}
int main(){
	//不能返回局部变量的引用
    // 返回错误: warning: reference to local variable ‘a’ returned
	int& ret01 = TestFun01();
	//如果函数做左值,那么必须返回引用
	TestFunc02();
	TestFunc02() = 100;
	TestFunc02();

	return 0;
}

执行结果

static int a : 20
static int a : 20
static int a : 100

注意事项

  • 不能返回局部变量的引用
  • 函数当左值,必须返回引用。

指针中的引用

在c语言中如果想改变一个指针的指向而不是它所指向的内容,函数声明可能这样:

void fun(int**); // 声明二级指针

给指针变量取一个别名。

Type* pointer = NULL;  
Type*& = pointer;

案例:

struct Person{
	int mAge;
};
//指针间接修改teacher的年龄
void AllocateAndInitByPointer(Person** person){
	*person = (Person*)malloc(sizeof(Person));
	(*person)->mAge = 200;  
}
//引用修改teacher年龄
void AllocateAndInitByReference(Person*& person){
	person->mAge = 300;
}
void test(){
	//创建Teacher
	Person* person = NULL;
	//指针间接赋值
	AllocateAndInitByPointer(&person);
	cout << "AllocateAndInitByPointer:" << person->mAge << endl;
	//引用赋值,将teacher本身传到ChangeAgeByReference函数中
	AllocateAndInitByReference(person);
	cout << "AllocateAndInitByReference:" << person->mAge << endl;
	free(person);
}

执行结果

AllocateAndInitByPointer:200
AllocateAndInitByReference:300

函数参数变成指针的引用,用不着取得指针的地址。

常量中的引用

常量引用的定义格式:

const Type& ref = val;

注意:

  • 字面量不能赋给引用,但是可以赋给const引用

  • const修饰的引用,不能修改

void test01(){
	int a = 100;
	const int& aRef = a; // 此时aRef就是a
	// aRef = 200; 不能通过aRef的值
	a = 100; //OK
	cout << "a:" << a << endl;
	cout << "aRef:" << aRef << endl;
    // 执行结果:
    // a:100
	// aRef:100
}
void test02(){
	// 不能把一个字面量赋给引用
	// int& ref = 100;
	// 但是可以把一个字面量赋给常引用
	const int& ref = 100; 
    // 等价于: int temp = 100; const int& ret = temp;
}

const引用使用场景

常量引用主要用在函数的形参,尤其是类的拷贝/复制构造函数。将函数的形参定义为常量引用的好处:

  • 引用不产生新的变量,减少形参与实参传递时的开销。

  • 由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用

    如果希望实参随着形参的改变而改变,那么使用一般的引用,如果不希望实参随着形参改变,那么使用常引用。

//const int& param防止函数中意外修改数据
void ShowVal(const int& param){}

引用的本质

引用的本质在c++内部实现是一个指针常量

Type& ref = val; // Type* const ref = &val;

c++编译器在编译过程中使用常指针作为引用的内部实现,因此引用所占用的空间大小与指针相同,只是这个过程是编译器内部实现,用户不可见。

//发现是引用,转换为 int* const ref = &a;
void testFunc(int& ref){
	ref = 100; // ref是引用,转换为*ref = 100
}
int main(){
	int a = 10;
	int& aRef = a; //自动转换为 int* const aRef = &a;这也能说明引用为什么必须初始化
	aRef = 20; //内部发现aRef是引用,自动帮我们转换为: *aRef = 20;
	cout << "a:" << a << endl;
	cout << "aRef:" << aRef << endl;
	testFunc(a);
	return 0;
}

参考资料

C++ 引用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值