形参对实参的影响

博客主要探讨函数形参对实参的影响。传值时,形参作用域在函数内,函数结束形参释放,实参传递给形参是赋值,形参改变不影响实参;传址时,若改变地址内容会影响实参,只改变地址则不影响;改变变量地址或一级指针需用二级指针;函数有返回值,不赋值给实参则实参不变。

形不改实

形参的改变一般不会影响实参的改变。

传值

void fun1(int a,int b)
{
	int t;
	t = a;
	a = b;
	b = t;
}
int main()
{
	int a=4,b=3;
	fun1(a,b);
	printf("%d %d\n",a,b);
	return 0;
}
输出:4 3

由上面的例子可以看出,实参的改变没有影响到实参的改变。
原因是形参a,b的作用域只在fun1函数里,函数结束形参也就被释放了。而且调用函数fun1时,实参传递给形参时,不是用实参替换形参,而是用实参给形参赋值!
相当于void fun1(int a=a,int b=b);第一个a或b为形参,第二个a或b为实参,在fun1里,a和b的交换是形参之间的交换,并没有影响实参。

传址

void fun2(int *a,int *b)
{
	int t;    //注意这里不能定义为int *t;//野指针
	t = *a;
	*a = *b;
	*b = t;
}
int main()
{
	int a=4,b=3;
	fun2(&a,&b);
	printf("%d %d\n",a,b);
	return 0;
}
输出:3 4

原因:将实参的地址赋值给形参,相当于void fun2(int *a=&a,int *b=&b);即形参指针a指向了实参a的地址,形参指针b指向了实参b的地址。*a 和 *b为指向的地址的内容。所以函数调用完会改变实参,将实参的值进行交换。

是不是传址就会影响到实参呢?
传址影响到实参的本质是将地址的内容进行改变,若只改变地址也不会影响到形参。

void fun3(int *a,int *b)
{
	int *t;   //这里定义了一个野指针,只要没有对它指向的地址的内容进行操作就不会出错,我们可以改变它的指向。
	t = a;//将指针t指向了指针a所指向的地址
	a = b;
	b = t;
}
int main()
{
	int a=4,b=3;
	fun2(&a,&b);
	printf("%d %d\n",a,b);
	return 0;
}
输出:4 3

原因:这里只是改变了指针的指向,并没有对指针指向的地址内的内容进行操作。fun3函数的作用是指针a指向了实参b的地址,指针b指向了实参a的地址,但指针a,b的生存期只在fun3函数里,函数调用完毕后,指针a,b就不存在了。

若要改变变量的地址或一级指针,则形参要定义为二级指针。
二级指针可以理解为地址的地址

void fun4(int **c,int **d)
{
	int *t;
	t = *c;
	*c = *d;
	*d = t;
}
int main()
{
	int a=4,b=3;
	int *p=&a,*q=&b,*m=&a,*n=&b;
	fun4(&p,&q);
	printf("%d %d %d %d\n",p,q,m,n);
	return 0;
}
输出:6422024 6422028 6422028 6422024

函数有返回值

int fun4(int m)
{
	m=4;
	return m;
}
int main()
{
	int a=3;
	fun4(a);
	b=fun4(a);
	printf("a=%d ,b=%d\n",a,b);
	return 0;
}
输出:a=3,b=4

当调用函数时,函数有返回值,但没有将函数赋值给实参,即函数返回值赋值给实参,则实参不会改变。虽然形参的作用域只在函数内,但函数的返回值会暂存在寄存器中,当函数赋值给实参时,会从寄存器中将返回值赋值实参。

<think>嗯,用户想了解C++中形参实参的关系及影响。首先,我需要回顾一下相关的概念。根据引用[4],实参是调用函数时提供的实际值,而形参是函数定义中声明的变量。接下来,要区分同的传递方式:值传递、引用传递和指针传递。 记得引用[3]提到,值传递时形参实参的拷贝,修改形参影响实参。而引用传递则是别名,修改形参会直接影响实参。比如例子中的x变为43,是因为传入了指针,修改了指向的值。这时候要说明同传递方式的具体影响。 另外,用户可能想知道为什么推荐使用引用而是指针,引用[3]和[5]都提到引用更安全,形式更简单,避免空指针异常。需要强调传引用的优点,比如const引用可以防止意外修改。 还要考虑使用场景,比如引用适合需要修改实参或避免拷贝大对象的情况,而指针适合需要可选参数的情况。引用[1]和[5]对此有说明,需要整合这些信息。 最后,用户可能需要示例来理解同情况下的结果差异。比如值传递改变实参,而引用传递会改变。可以举int类型和数组的例子,说明数组名作为指针传递时的情况。 还要注意生成相关问题,帮助用户深入理解。比如性能差异、const引用的作用、指针和引用的区别等。这些问题应该基于引用中的知识点,确保覆盖用户可能关心的其他方面。</think>### C++形参实参的关系及影响 #### 1. 基本概念 - **形参**:函数定义中声明的参数,用于接收实参传递的值或引用。例如: ```cpp void func(int param) { ... } // param是形参 ``` - **实参**:调用函数时实际传入的参数,可以是常量、变量或表达式。例如: ```cpp int x = 10; func(x); // x是实参 ``` #### 2. 传递方式对实参影响 ##### (1) 值传递(默认方式) - **特点**:形参实参的独立拷贝,修改形参**影响**实参[^3]。 - **示例**: ```cpp void changeValue(int val) { val = 100; // 修改形参 } int main() { int x = 10; changeValue(x); cout << x; // 输出10(实参未变) } ``` ##### (2) 引用传递 - **特点**:形参实参的别名,修改形参**直接影响**实参。 - **示例**: ```cpp void changeRef(int &ref) { ref = 100; // 修改引用形参 } int main() { int x = 10; changeRef(x); cout << x; // 输出100(实参被修改) } ``` ##### (3) 指针传递 - **特点**:传递内存地址,通过解引用操作修改指针指向的值会影响实参[^5]。 - **示例**: ```cpp void changePtr(int* ptr) { *ptr = 43; // 修改指针指向的值 } int main() { int x = 10; changePtr(&x); cout << x; // 输出43(实参被修改) } ``` #### 3. 关键区别总结 | 传递方式 | 形参类型 | 内存操作 | 实参是否受影响 | |----------|---------------|------------------|----------------| | 值传递 | 普通变量 | 复制值 | 否 | | 引用传递 | 引用类型 | 直接操作原变量 | 是 | | 指针传递 | 指针类型 | 通过地址间接操作 | 是(需解引用) | #### 4. 使用场景建议 - **优先使用引用**:避免指针操作风险,语法更简洁,支持`const`引用防止意外修改。 ```cpp void processData(const string &str); // 避免拷贝大对象 ``` - **指针的适用场景**:需明确传递空值或可选参数时[^1]。 ```cpp void findNode(Node* parent = nullptr); ``` #### 5. 特殊类型的影响 对于数组参数,传递的是首地址的指针(即使写成数组形式): ```cpp void modifyArray(int arr[]) { arr[0] = 100; // 实际修改原数组 } int main() { int nums[3] = {1,2,3}; modifyArray(nums); // nums[0]变为100 } ```
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值