函数的形参(普通形参、指针形参、引用形参)

本文详细解析了编程中普通形参、指针形参和引用形参的工作原理,强调了它们如何影响实参,并指出在修改实参值方面的区别。通过实例说明,帮助读者掌握形参与实参在内存管理上的差异和使用技巧。

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

以一些代码段为例:

1、普通形参

int n=10;
add1(n);

void add1(int v1) 
{ 
	v1+=1;//对实参无影响 
}

这是最普通的形参方式,形参仅仅为实参的一个副本,对形参的任何操作不会修改实参的值。例中对v1的操作只是修改了实参的一个副本。实参不变

2、指针形参

int *p=&n;

add2 (p) ;//p为指向n的指针
//或者直接
add2(&n)

void add2(int *p) 
{ 
	*p+=1;//实参才会变 
	p+=1;//对实参无影响 
	(*p)++;//实参才会变
}

使用指针做为函数的形参,只有对指针所指对象进行的操作才会改变实参的值。要实现改变实参,还有一种更安全更自然的方法——引用形参。

在执行 add2(&n) 时,系统在内存分配表里增加了一行add2中的p,其地址为新地址,值为&n。操作*p,即是在操作n了。有点类似引用,*p即为n的一个别名

3、引用形参

int a=1,b=2;
swap(a,b);

void swap(int &a,int &b) 
{ 	int temp=a; 
	a=b; //会改变实参的值 
	b=temp; //会改变实参的值 
}

引用形参直接关联到其所绑定的对象,而非这些对象的副本。 所以这种方法可以修改实参的值,而且更加直观。

函数的形参和实参具有以下特点:

1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。

2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。

3.实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。

4.函数调用中发生的数据传送是单向的。即只能把实参的值传送给形参而不能把形参的值反向地传送给实参。 因此在函数调用过程中,形参的值发生改变,而实参中的值不会变化。故需要手动修改才可。

<think>嗯,用户的问题是关于C++中常量指针和常量引用作为函数形参的优点。首先,我需要回忆一下常量指针和常量引用的基本概念,以及它们在函数参数中的应用。 首先,根据引用资料中的内容,比如引用[3]提到,使用指向常量的指针或常量引用作为形参可以提高函数的灵活性,因为它们可以接受常量和非常量参数。如果函数内部不会修改这些参数,这样定义会更安全,也避免误导调用者。 然后,用户可能想知道具体的优点有哪些。我需要整理这些优点,可能包括安全性、灵活性、代码可读性等方面。比如,安全性方面,防止意外修改;灵活性方面,可以接受更多类型的参数;可读性方面,明确函数不会修改参数,让代码更清晰。 接下来,用户可能对如何正确使用这些形参有疑问。比如,在函数定义时,如果参数不需要被修改,应该优先使用常量指针或常量引用。例如,在引用[4]中的cube2函数使用了常量引用,这样既可以接受const和非const的变量,还能避免修改原始数据。 另外,需要注意常量指针指针常量的区别。根据引用[1]和[2],常量指针是指指针本身是常量,不能指向其他地址,而指向常量的指针是指指针指向的内容不可变。但在函数参数中,通常使用指向常量的指针(const int* p)或者常量引用(const int& x),来保证不修改数据。 可能还需要解释为什么使用这些形参普通指针引用更好,比如避免临时对象的创建,或者允许传递字面值。例如,引用[3]提到,如果形参普通引用,就不能接受字面值或const对象,而常量引用可以。 然后,我需要组织这些点,用清晰的结构回答用户的问题,比如分点列出优点,每个优点结合引用中的例子说明。同时,可能需要给出代码示例,比如展示使用常量引用作为参数的函数,以及如何调用它,这样用户更容易理解。 最后,生成相关问题,帮助用户深入理解。比如,询问为什么普通引用不能接受常量参数,或者在不同情况下如何选择指针引用等。</think>在C++中,使用常量指针和常量引用作为函数形参有以下核心优点: --- ### 一、安全性优势 1. **防止意外修改** - 常量指针(`const int* p`)或常量引用(`const int& x`)明确告知编译器:该参数在函数内部**不可被修改**。例如: ```cpp void print(const int* arr, int size) { // arr[0] = 5; // 编译错误:无法修改常量指针指向的数据 } ``` - 避免函数内部对参数的误操作,保护原始数据完整性[^3]。 2. **防御恶意修改** 通过限制写权限,防止外部传入的数据被非法篡改,尤其在处理第三方库或关键数据时尤为重要[^4]。 --- ### 二、灵活性提升 1. **兼容多种参数类型** 常量指针/引用可以同时接受**常量**和**非常量**参数,例如: ```cpp void process(const string& str); // 可接受 string s 或 const string s ``` 若使用普通引用(`string& str`),则无法接受常量参数或字面值(如`process("test")`)。 2. **支持临时对象和字面值** 常量引用允许直接传递临时对象,例如: ```cpp int result = cube2(10); // 正确:常量引用可绑定字面值 ``` 普通引用无法实现此功能。 --- ### 三、代码可读性与设计规范 1. **明确函数行为** 使用常量参数向调用者表明该函数**不会修改输入参数**,例如: ```cpp int calculate(const vector<int>& data); // 明确告知调用者data不会被修改 ``` 这种设计能减少调用者的心理负担。 2. **遵循最小权限原则** 仅开放必要的访问权限(只读),符合软件工程的安全设计理念。 --- ### 四、性能优化 - **避免拷贝开销** 常量引用传递大型对象时无需拷贝(如`const vector<int>&`),同时保证数据安全,比按值传递更高效。 --- ### 代码示例对比 ```cpp // 普通引用:仅能接受非常量参数 void unsafeModify(int& x) { x = 100; } // 可能误导调用者认为会修改参数 // 常量引用:接受所有类型参数 void safeRead(const int& x) { cout << x; // 仅读取,无修改权限 } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值