详解const引用和常量指针、指向常量的指针

  • const对象一旦创建,其值将不可更改,所以const变量必须初始化。
  • 只要不改变const的值,const变量就和其他变量一样

1.const对象在多个文件中:

  • 默认情况下,被const修饰的对象仅在文件内中有效 。这就意味着允许多个文件中定义同名的const变量,实际就等同于分别在文件中定义了独立的变量。举例如下:

main.cpp中定义了const变量MainSize:

#include <iostream>
using namespace std;
extern void test();

const int MainSize = 100;
int main()
{
	int MainVal = MainSize;

	std::cout << "MainVal = " << MainVal << std::endl;
	test();

	system("pause");
	return 0;
}

test.cpp中也定义了const变量MainSize:

#include <iostream>
const int MainSize = 200;
void test()
{
	int TestVal = MainSize;
	std::cout << "TestVal = " << TestVal << std::endl;
}

运行后的结果:
在这里插入图片描述

  • 那么,如何做到多个文件中使用同一个const变量呢?也就是说,只在一个文件中定义const,而在其他文件中声明并使用它。解决方案是使用extern关键字,但是和一般的变量不同,必须在定义和声明处都加上extern

main.cpp中定义了extern const变量MainSize:

#include <iostream>
using namespace std;
extern void test();

extern const int MainSize = 100;
int main()
{
	int MainVal = MainSize;

	std::cout << "MainVal = " << MainVal << std::endl;
	test();

	system("pause");
	return 0;
}

test.cpp中声明了const变量MainSize:

#include <iostream>

extern const int MainSize;
void test()
{
	int TestVal = MainSize;
	std::cout << "TestVal = " << TestVal << std::endl;
}

运行结果:
在这里插入图片描述

2.const 的引用

  • 非常量引用指向一个常量对象是不允许的。因为常量对象本就意味则不变,若是允许此语法,那不就可以改变常量对象了吗!
const int MainVal = 100;

const int& rMainVal = MainVal; //正确
int &rMainVal2 = MainVal;//error:无法从“const int”转换为“int &”
  • 初始化常量引用(对const的引用)时,允许用任意表达式作为初始值,只要任意表达式能转换为引用类型
int i = 42;
const int& r1 = i; //允许将常量引用绑定到一个普通int对象上
const int& r2 = 55; //正确
const int& r3 = r1*2; //正确

为什么C++会允许上述操作?原因在于编译器在编译的过程中,会生成一个const的临时变量,最后我们要的引用实际都指向这个临时变量。下面请看C++ primer 第5版中给出的例子:
在这里插入图片描述
结合上面的描述,我们也不难想到,为什么下面的初始化不行:(因为若是允许,那么修改ri或r3的值只是修改了临时变量,并没有改变dval和r1的值,而我们的目的就是改变其值,所以C++把这种行为定为非法)

int i = 42;
double dval = 3.14;

int& r1 = i; //正确,标准的引用
int &ri = dval; //错误
int& r3 = r1*2; //错误
  • 实例
#include <iostream>
using namespace std;

int main()
{
	int i = 42;
	const int& r1 = i;
	const int& r2 = 55;
	const int& r3 = r1 * 2;

	std::cout << "r2 = " << r2 << std::endl;
	
	std::cout << "&i =  " << &i  << " ; " << "i = " << i << std::endl;
	std::cout << "&r1 = " << &r1 << " ; " << "r1 = " << r1 << std::endl;
	std::cout << "&r3 = " << &r3 << " ; " << "r3 = " << r3 << std::endl;

	std::cout <<"改变i值后"<< std::endl;

	i = 50;

	std::cout << "&i =  " << &i << " ; " << "i = " << i << std::endl;
	std::cout << "&r1 = " << &r1 << " ; " << "r1 = " << r1 << std::endl;
	std::cout << "&r3 = " << &r3 << " ; " << "r3 = " << r3 << std::endl;
	
	const int& r4 = r1 * 2;
	std::cout << "&r4 = " << &r4 << " ; " << "r4 = " << r4 << std::endl;

	system("pause");
	return 0;
}

打印结果:
在这里插入图片描述

2.1const 指针的引用

前面我们有将常量引用指向非常量,如下

int i = 42;
const int& r1 = i; //允许将常量引用绑定到一个普通int对象上

那么,对指针是否如此呢?看下面的例子:

int a = 10;
int *p = &a;
const int* &rp = p;

最后一句是否正确?答案是否定的,因为尽管初始化常量引用(对const的引用)时,允许用任意表达式作为初始值,但我们不能忘了只要任意表达式能转换为引用类型这句话,p是一个指针,它只能转换为常量指针,所以正确的做法是:
int* const &rp = p;

3.常量指针和指向常量的指针

3.1. 常量指针

3.2. 指向常量的指针

3.3. 两者结合

3.4. 如何区分常量指针和指向常量的指针

  • 常量指针
    顾名思义,说明指针是个常量,而指针代表地址,所以常量指针是不能改变指向的指针

在这里插入图片描述

int errNumb = 0;
int myerrNumb = 1;

int *const curErr = &errNumb; //定义常量指针
curErr = &myerrNumb;//错误:不能给常量赋值
  • 指向常量的指针
    既然指向常量,当然不能改变其值,但可改变指向

但是请注意:仅仅只是不能通过指针修改,但可以通过变量修改。如

double p2 = 3.1415const double *cptr = &p2;

*cptr = 1.1111;是错位的;但p2 = 1.1111是正确的。

在这里插入图片描述

const double pi = 3.14;
const double *cptr = &pi; //定义指向常量的指针
*cptr = 3.1415;//错误:不能给常量赋值

double pi2 = 3.1415;
cptr = &pi2;//改变指向,指向一个非常量对象
std::cout << *cptr << std::endl;
//通过变量修改cptr指向地址的值
pi2 = 1.111;
std::cout << *cptr << std::endl;

打印结果:
在这里插入图片描述

  • 两者结合

既:指向一个常量对象的常量指针。兼具两者的特性:既不能改指向,也不能改值
在这里插入图片描述

  • 如何区分常量指针和指向常量的指针
int *const curErr = &errNumb; //常量指针
const double *cptr = &pi; //指向常量的指针

看const修饰谁,第一个修饰的curErr,它存的是地址,当然是指向不变;第二个修饰*cptr,修饰的是一个值,当然是不能改变值。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值