前言:我们知道普通变量、指针、函数形参,加上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引用函数能正确生成并使用临时变量;
以上便是文章的全部内容,感谢观看!