c++primer之const

本文详细介绍了C++中const关键字的多种用法,包括const对象的初始化、作用域、常量引用、指向常量的指针以及顶层const和底层const的区别。通过示例代码展示了const在不同场景下的应用,强调了const在限制对象修改和保证程序稳定性方面的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、const对象一旦创建后其值就不能再改变,所以const对象必须初始化。

二、默认情况下,const对象被设定为仅在文件内有效,多个文件种出现同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。

三、只在一个文件中定义const,在其他多个文件中要想声明并使用它,可以添加extern关键字。

四、可以把引用绑定到const对象上,就像绑定到其他对象上一样, 我们称之为常量的引用,对常量的引用不能被用作修改它所绑定的对象。

五、引用的类型必须与其所引用对象的类型一致,但有2个例外:

1、在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型。

2、允许一个常量引用绑定非常量的对象、字面值,甚至时一个一般表达式。

六、对const的引用可能引用一个并非const的对象,常量引用仅对引用可参与的操作做出限定,对于引用的对象本身不是一个常量未做限定,因为对象也可能是个非常量,所以允许通过其他途径修改它的值。

七、指向常量的指针不能用于改变其所指向对象的值,要想存放常量对象的地址,只能使用指向常量的指针。

八、所谓指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他途径改变

十、允许指针本身定为常量,常量指针必须初始化,且一旦初始化完成,则它的值就不能被改变,把*放在const关键字之前用以说明指针是一个常量,这样的书写形式也意味着不变的是指针本身的值而不是指向的那个值。

十一、用名词顶层const表示指针本身是一个常量。用名称底层const表示指针指向的对象是一个常量。顶层const可以表示任意的对象是常量,底层const则于指针和引用等复合类型的基本部分有关。

十二、当执行对象的拷贝操作时,顶层const不受任何影响,而拷入和拷出的对象必须具有相同的底层资格,或者两个对象的数据类型必须能够转换。

十三、常量表达式是指值不会改变并且在编译过程就能得到结算结果的表达式。

十四、c++11中允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式,声明为constexpr的变量一定是一个常量,且必须用常量表达式初始化。

十五、一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象.

十六、在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,于指针所指的对象无关.

 

const int ci = 1024;
	const int& r1 = ci;
	cout << r1 << endl; // 1024

	//r1 = 41; // 错误,r1是对常量的引用,不能被修改
	//int& c2 = ci; // 错误, 试图可以通过r2来改变它引用的对象的值,而引用的对象是对常量的引用

	double dval = 3.14;
	// 这里相当于rd绑定了一个临时量,
	// const int temp = dval;
	// const int &rd = temp;
	const int& rd = dval; 
	//int& rd = dval; //  如果rd不是常量,就允许对rd赋值,这样就会改变rd所引用对象的值, 而所引用的是double型,会有类型转换错误
	cout << rd << endl;

	// 常量的引用仅对可参与的操作做出了限定,对于引用的对象本身是不是一个常量未做限定
	// 因为对象也可能是一个非常量,所以允许通过其他途径改变它的值
	int j = 42;
	int& j1 = j;
	const int& j2 = j; 
	j1 = 0; // j1并非常量,i的值可以被j1修改
	// j2 = 0; // 错误,j2是一个常量引用,j的值不能被j2修改


	const double pi = 3.14;
	// double* ptr = &pi; // 错误,ptr是一个普通指针
	const double* cptr = &pi;
	//*cptr = 42; //错误,指向常量的指针不能用于改变其所指向对象的值

	int errNum = 0;
	int* const curErr = &errNum; // curErr是一个常量指针
	cout << *curErr << endl;
	*curErr = 1; // curErr指向的是一个非常量整数,所以可以通过curErr修改errNum的值
	cout << errNum << endl;
	cout << *curErr << endl;
	const double pi2 = 3.14;
	const double* const pi2p = &pi2; // pi2p是一个指向常量对象的常量指针
	//double* const pi2p = &pi2; // 错误,因为pi2是一个常量,指向常量的指针不能用于改变其所指向对象的值
	cout << *pi2p << endl;

	
	int x = 1;
	int y = 2;
	int* const x1 = &x; 
	cout << *x1 << endl; // 1
	*x1 = 4; // x1指向的是一个非常量整数,所以可以通过x1修改x的值
	//x1 = &y; // x1本身是一个常量对象,不能再次引用另一个对象
	cout << *x1 << endl; // 4

	const int* x2 = &x; 
	cout << *x2 << endl; // 4
	// *x2 = 5; 错误, x2 是一个指针常量,所以不能通过x2修改x的值
	x2 = &y;  // x2 可以再次引用另一个对象
	cout << *x2 << endl; // 2

	// 顶层const表示指针本身是一个常量
	// 底层const表示指针指向的对象是一个常量
	int p = 0;
	int* const p1 = &p; // 顶层const
	const int p2 = 45; // 顶层const
	const int* p3 = &p2; // 底层const
	const int* const p4 = p3; // 第一个const是底层const, 第二个const是顶层const
	const int& p5 = p2; // 用于声明引用的const都是底层const
	// 在执行对象的拷贝操作时
	// 顶层const不受影响
	p = p2; // p2时一个顶层const
	// 拷入和拷出的对象必须具有相同的底层const资格,或者2个对象的数据类型必须能够转换,
	p3 = p4; // p3 和 p4都是底层const


	const int maxFile = 20; // 常量表达式
	const int fileLimit = maxFile + 1; // 常量表达式
	//  const int sz = getSize(); // 不是常量表达式, getSize()的值需要在运行时才能获取到
	// 允许将变量声明为constexper类型以便由编译器来验证变量的值是否为一个常量表达式
	// 声明为constexper的变量一定是一个常量,且必须用常量表达式初始化
	constexpr int maxFile1 = 20; // 常量表达式
	constexpr int fileLimit1 = maxFile1 + 1; // 常量表达式
	// constexpr int sz1 = getSize(); // 只有 当getSize()是一个constexpr函数时才是一条正确的声明语句

	// 在constexpr声明种如果定义了一个指针,限定符constexpr仅对指针有效,与指针指向的对象无关
	const int* m = nullptr; // m是一个指向整型常量的指针
	constexpr int* n = nullptr; // n是一个指向整数的常量指针
	// constexpr指针即可以指向常量也可以指向非常量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值