概述
在C/C++语言中值传递、指针传递和引用传递(C++ only)这三种函数参数传递方式是比较基本的知识,用的比较普遍,但不仔细分析其实质的话,时间长容易记混了。网上的资料也较多但多数都不系统,本文力求用最白话的表达和简单的示例把这三种方式描述清楚。没时间看分析的直接看简述就可以了。
简述
值传递就是最普通的传递方式,比如函数定义为fun(int a)
,在调用的地方有int x=6
, 使用fun(x)
就可以了。这种方式在fun(int a)
函数内部的对a的修改 不能 导致外部x的变化。
指针传递其实也就是地址传递,函数定义为fun(int *a)
,形参为指针,这就要求调用的时候传递进去一个参数的地址,例如int x=6;
fun(&x)
。 这种方式在fun(int a)
函数内部的对a的修改 能 导致外部x的变化。
引用传递只有C++支持,相比前两种方式用的比较少,但也非常有用。引用传递函数定义为fun(int &a)
,这里&符号是引用而不是取地址的意思,调用方式和值传递类似,例如int x=6;
fun(x)
。 但是这种方式在fun(int a)函数内部的对a的修改 能 导致外部x的变化。
表格是一种比较直接的表达方式,列个表格可以对这三种方式一目了然,假设调用fun函数之前都有定义int x=6,这三种方式异同如下表所示:
传递方式 | 函数定义 | 函数调用 | 函数内对a修改的影响 |
---|---|---|---|
值传递 | fun(int a) | fun(x) | 外部x不变 |
指针传递 | fun(int *a) | fun(&x) | 外部x同步更改 |
引用传递(C++) | fun(int &a) | fun(x) | 外部x同步更改 |
分析
下面三部分代码都尝试在swap函数内对输入参数进行数值交换,通过打印其数值和指针来分析。
值传递
函数内部使用这个参数,对这个参数的修改对函数外的原始数据不起作用。
示例:
#include <stdio.h>
void swap(int a, int b){
printf("swap entern");
printf("a = %d, ptr = %pn", a, &a);
printf("b = %d, ptr = %pn", a, &b);
int tmp = b;
b = a;
a = tmp;
printf("a = %d, ptr = %pn", a, &a);
printf("b = %d, ptr = %pn", b, &b);
printf("swap leaven");
}
int main() {
int x = 1;
int y = 2;
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
swap(x, y);
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
return 0;
}
运行结果:
x = 1, ptr = 000000000022FE4C
y = 2, ptr = 000000000022FE48
swap enter
a = 1, ptr = 000000000022FE20
b = 1, ptr = 000000000022FE28
a = 2, ptr = 000000000022FE20
b = 1, ptr = 000000000022FE28
swap leave
x = 1, ptr = 000000000022FE4C
y = 2, ptr = 000000000022FE48
结果表明:
swap函数内部a b
的数值进行交换,但是没有影响到x y
的值。swap函数形参a b
所指向的内存地址和外部x y
的地址不一样。
实质:
swap为形式参数 a b
创建了内存空间,main函数调用swap函数的时候,把x y
的值copy给新创建的 a b
。a b
和x y
分别在不同的内存位置中,因而对这个新创建的 a b
操作不会影响外部的 x y
的值。
带有返回值的函数,比如
int fun(){int x=7; return x}
,外部调用方式为int a=fun();
,这时是把x的数值copy了一份给外部a所在的内存空间,并释放了x所在的内存空间(系统自动分配的栈内存),在fun函数调用后即使知道x的内存地址也可能取不到相应的数据。
返回值为指针的函数,比如char *fun(){...; return str;}
,函数中待返回的变量必须是使用malloc等函数手动申请空间(堆内存)的数据,且外部使用后要手动释放。因为系统自动申请的栈内存会在函数调用后自动释放。
指针传递(地址传递)
形参为指向实参地址的指针,当对形参的指向操作时,就相当于操作实参本身。
示例:
#include <stdio.h>
void swap(int *a, int *b){
printf("swap entern");
printf("a = %d, ptr = %pn", *a, a);
printf("b = %d, ptr = %pn", *a, b);
int tmp = *b;
*b = *a;
*a = tmp;
printf("a = %d, ptr = %pn", *a, a);
printf("b = %d, ptr = %pn", *b, b);
printf("swap leaven");
}
int main() {
int x = 1;
int y = 2;
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
swap(&x, &y);
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
return 0;
}
运行结果:
x = 1, ptr = 000000000022FE4C
y = 2, ptr = 000000000022FE48
swap enter
a = 1, ptr = 000000000022FE4C
b = 1, ptr = 000000000022FE48
a = 2, ptr = 000000000022FE4C
b = 1, ptr = 000000000022FE48
swap leave
x = 2, ptr = 000000000022FE4C
y = 1, ptr = 000000000022FE48
结果表明:
swap函数内部a b
的数值进行交换,外部的x y
的值也发生了交换。swap函数形参a b
所指向的内存地址和外部x y
的地址分别都相同。
实质是:
swap函数形式参数其实是一个指针,可能把fun(int *a)
写成fun(int* a)
就比较容易理解了,形参a为地址指针。*a
就是x
,a
就是&x
。函数内部要想修改其数值就要使用*a
取数值,打印其地址直接打印a
就可以了。
函数内部对a b
的操作实际上是操作x y
所在的内存空间,所以函数内的修改会影响到外部x y
的数值。
引用传递
引用传递的形参加一个&符号,这个形参相当于实参的一个别名,对形参的操作都相当于对实参的操作。
注意形参带&符号的引用传递在C语言中是不可用的,只有C++中支持。
C语言中函数参数总是通过值传递,可以通过显式传递指针值模拟引用传递。
Function parameters are always passed by value. Pass-by-reference is simulated in C by explicitly passing pointer values. – https://en.wikipedia.org/wiki/C_(programming_language)
示例:
#include <stdio.h>
void swap(int &a, int &b){
printf("swap entern");
printf("a = %d, ptr = %pn", a, &a);
printf("b = %d, ptr = %pn", a, &b);
int tmp = b;
b = a;
a = tmp;
printf("a = %d, ptr = %pn", a, &a);
printf("b = %d, ptr = %pn", b, &b);
printf("swap leaven");
}
int main() {
int x = 1;
int y = 2;
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
swap(x, y);
printf("x = %d, ptr = %pn", x, &x);
printf("y = %d, ptr = %pn", y, &y);
return 0;
}
运行结果:
x = 1, ptr = 000000000022FE4C
y = 2, ptr = 000000000022FE48
swap enter
a = 1, ptr = 000000000022FE4C
b = 1, ptr = 000000000022FE48
a = 2, ptr = 000000000022FE4C
b = 1, ptr = 000000000022FE48
swap leave
x = 2, ptr = 000000000022FE4C
y = 1, ptr = 000000000022FE48
结果表明:
函数内对形参的使用方式和值传递相同,产生的效果和指针传递相同。
swap函数内部a b
的数值进行交换,外部的x y
的值也发生了交换。swap函数形参a b
所指向的内存地址和外部x y
的地址分别都相同。
实质是:
形式参数前加&符号,这个形参相当于实参的一个别名,对这个形参的操作等同于对实参的操作,有点类似快捷方式。a
等同于x
,比如fun(int &a)
函数内对a的操作和值传递的函数fun(int a)
中对形参的操作一样,但是修改形参同时也是修改实参。
最后
以上就是玩命西牛为你收集整理的C/C++语言中值传递、指针传递和引用传递的全部内容,希望文章能够帮你解决C/C++语言中值传递、指针传递和引用传递所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复