C++ primer 6.2.3 const形参和实参

本文深入探讨C++中const修饰符的用法及其在不同上下文中的含义,特别是顶层const与底层const的区别,以及如何在函数参数中合理使用const引用以提高代码效率。

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

顶层const作用与对象本身

const int ci = 42;//不能改变ci,const是顶层的
int i = ci;//正确:当拷贝ci 时,忽略了它的顶层const(就是说顶层const所指对象可以拷贝但不可以改变)
//ci = 43;报错
int *const p = &i;//const是顶层的,不能给p赋值(此时const修饰的 int *,即p是地址别名)
//int *const p = 2;不能给p赋值
//所以
*p = 0;//可以用p去修改i的值

所以当形参有顶层const,传给它常量对象或者非常量对象都是可以的:

void func(const int i){
//i = 42;报错
//func能够读取i 但是不能向i写值
}

指针或引用形参与const
可以用非常量来初始化一个底层const对象,但是不能用一个底层const对象来初始化一个非常量,一个普通的引用必须用同类型的对象初始化

	int i = 42;
	const int* cp = &i;//正确:但是cp不能改变i(因为这是底层const,const修饰的指向i的地址的别名cp)

	const int& r = i;//正确:但是r不能改变i(因为这是常量引用,只能初始化不能改变值)

	const int& r2 = 42;//正确:这是一个常量引用
	
	int* p = cp;//错误 p是int*类型,cp是const int* 类型
	
	int& r3 = r;//错误 r3是 int&类型,r是const int& 类型

	int& r4 = 10;//错误不能用字面值初始化一个非常量引用

在参数传递上是同样的规则

void reset(int& i){i = 0;};
int main{
	int i = 0;
	const int ci = i;
	string::size_type ctr = 0;
	reset(&i);//错误调用的是int*的reset函数
	reset(&ci);//错误不能用指向const int 对象的指针初始化int*
	reset(ci);//错误不能把普通引用绑定掉const对象ci上
	reset(42);//错误不能把普通引引用绑定到字面值上
	reset(ctr);//错误类型不匹配
}

C++允许用字面值初始化常量引用,但是不能用字面值初始化非常量引用

函数形参尽量用常量引用
把函数定义为普通引用形参,会导致函数修改了实参的值,使用普通引用会限制函数所能接收的实参类型

6.2.3节练习
练习6.16
把函数定义为普通引用形参,会导致函数修改了实参的值,使用普通引用会限制函数所能接收的实参类型

bool is_empty(const string& s) {
	return s.empty();
}

练习6.17

#include<string>
#include <iostream>
#include<cctype>
using namespace std;
bool capital(const string& word) {//因为参数不需要更改所以用了const
	for (auto a : word) {
		return isupper(a);
	}
}
string lowerCase(string word) {//不能使用const,因为参数需要修改
	for (auto &i : word) {//此处用引用的方式才能完整的更改完字符串
		if (isupper(i))
			i = towlower(i);
		
	}
	return word;
}
int main()
{
	cout << capital("hello") << endl;
	cout << lowerCase("HELLO") << endl;
	system("pause");
	return 0;
}

练习6.18

(a):
bool compare(const matrix &m1, const matrix &m2);
 
(b):
vector<int>::iterator change_val(int, vector<int>::iterator);

练习6.19

(a) calc(23.4, 55.1);                   // 不合法, 函数只有一个形参,传入两个实参不合法
(b) count("abcda", 'a');                // 合法
(c) calc(66);                           // 合法
(d) sum(vec.begin(), vec.end(), 3.8);   // 合法

练习6.20
参数不需要修改时用常量引用
如果参数原本时常量引用,将它改为普通引用会导致程序编译不通过,还有可能会改变函数的实现结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值