C++对const引用的特殊处理、为什么函数形参的引用建议加上const?只是为了防止值被修改吗?

前言:我们知道普通变量、指针、函数形参,加上const修饰表示不可改变,但是引用前面加上const就有特别之处了

目录

const日常使用

const引用的特别处理

        const引用创建临时变量规则

引用形参声明为const的三个理由


const日常使用

我们知道如果我们想修改函数传入的实参的值,我们就必须传地址,也就说值传递,值传递有两种方式,一是传引用,而是传指针;

先看示例代码:

#include <iostream>
using namespace std;

// 传指针
void PModify(int* age, string* name)
{
	*age = 20;
	*name = "指针法";
	cout << "指针法函数内部输出:" << *age << " " << *name << endl;
}

// 传引用
void CModify(int& age, string& name)
{
	age = 33;
	name = "引用法";
	cout << "引用法函数内部输出:" << age << " " << name << endl;
}

int main()
{
	// 写一个函数修改下面两个变量的值
	int age = 10;
	string name = "赵四";

	PModify(&age, &name);

	cout << "修改后:" << age << " " << name << endl;

	cout << endl;

	CModify(age, name);

	cout << "修改后:" << age << " " << name << endl;

	return 0;
}

运行:

 

没有问题,引用法和指针法都正确的修改了变量的值;

下面我们把形参全部都加上const:

出错了,const形参不能被修改内容;这也是const引用的用途之一:防止实参被修改 

但是,const引用还有一个很特别的用途,下面为大家介绍

const引用的特别处理

先把代码写成这样:

#include <iostream>
using namespace std;

// 传指针
void PModify(int* age, string* name)
{
	cout << "指针法函数内部输出:" << *age << " " << *name << endl;
}

// 传引用
void CModify(int& age, string& name)
{
	cout << "引用法函数内部输出:" << age << " " << name << endl;
}

int main()
{
	// 写一个函数修改下面两个变量的值
	int age = 10;
	string name = "赵四";

	PModify(&age, &name);

	CModify(age, name);

	return 0;
}

const全部去掉,主函数就调用这两个输出函数就行了,另外注意,这个时候主函数调用PModify和CModify的时候,传入的实参是变量;

运行一下:

正常输出没有问题;

那么我们如果实参传入常量呢?字面量?如下:

 

编译不通过,因为他需要的是一个地址,我们这里传了一个常量,肯定不行啊;

那么形参是引用的函数可以吗?(盲猜一下不可以):

 

也不行;

我这里先展示解决方法,再为大家讲解为什么;

我们只需要在引用形参前面加上const,那么就可以传入常量了,如下:

那么指针也有这种待遇吗?

 

还是不行,这是为什么呢?

因为C++对引用的const做了优化,他会创建临时变量,让引用指向临时变量;

        const引用创建临时变量规则

什么时候将会创建临时变量呢?

1、引用为const

2、数据对象的类型是正确的,但不是左值

3、数据对象的类型不正确,但是可以转换为正确的类型

我们先来讲一下什么是左值,什么是右值:

左值是可以被引用的数据对象,可以通过地址访问他们,例如:变量、数据元素、结构体成员、引用和解引用的指针;

右值包括字面常量(用双引号包含的字符串除外)和包含多项的表达式

首先第一点引用为const这是必须的,也不需要证明;

再看第二点

怎么理解这句话呢?下面我为大家举个栗子:

看过我之前的文章《引用和指针》的小伙伴应该知道,引用的本质也是取地址,那么这个常量(右值)8我们可以取地址吗?

不可以;所以编译未通过啊;

那么我们加上const呢?

编译通过了,是因为加上const之后,常量(右值)8就是个地址或者是就是个左值了吗?

不是的 

是因为满足了条件2,成功的触发了创建临时变量的功能!

就是这个道理,类型匹配的但不是左值的时候,如果我们的引用是const,那么他就会创建临时变量;

他的本质和下面两行代码没有区别:

红框1==红框2;

再看第三点:数据对象的类型不正确,但是可以转换为正确的类型;

先看代码:

#include <iostream>
using namespace std;

// 传指针
void PModify(const int* age, const string* name)
{
	cout << "指针法函数内部输出:" << *age << " " << *name << endl;
}

// 传引用
void CModify(const int& age, const string& name)
{
	cout << "引用法函数内部输出:" << age << " " << name << endl;
}

int main()
{
	CModify(18, "赵四");

	return 0;
}

运行:

没有问题,正确输出;

上面说的是类型不匹配,但是可以转为正确的类型,那么我们改改:

 

这下类型不匹配了,再次运行:

 

成功输出!

我们把const去掉会怎么样呢?这里我全部去掉,大家自己可以尝试,去掉哪一个都会报错:

 

去掉const报错了,加上const就成功输出,这说明const有在为'X'和"赵四"创建临时变量; 

可能有人会问,这个测试哪里满足了观点3?

观点3:类型不匹配,可以转换为正确的类型

测试里:

'X'是字符,和int不匹配吧,但是我们都知道,字符实质上就是整数,所以可以转换为正确的类型没有问题吧;

"赵四"的类型是const char*,string的本质也是一个char*的容器,所以"赵四"也能正确的转换为string类型;

这两个参数都满足观点3,所以形参引用加上const就会创建临时变量,程序运行也就不会有问题;

引用形参声明为const的三个理由

1、使用const引用可以避免无意中修改数据的编程错误;

2、使用const引用使函数能够处理const和非const实参,否则只能接收非const实参;

3、使用const引用函数能正确生成并使用临时变量;

以上便是文章的全部内容,感谢观看!

  • 8
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值