解释下 传值方式 和 传址方式
发布网友
发布时间:2022-03-25 19:38
我来回答
共1个回答
热心网友
时间:2022-03-25 21:07
问str为什么没有变。然后将void GetMemory改成:
void GetMemory(char **p, int num)
{
*p=(char *)malloc(sizeof(char) * num);
}
str就变了。
问这是为什么?先来看看什么是传值,什么是传址。
传值方式:向函数传递参数时,先复制一份参数,然后才将复制品传给参数。函数中所有对参数的操作,就只是在使用复制品。不会对改变传递前的参数本身。
传址方式:将地址传送给函数,函数对该地址的内容操作,相当于对实参本身的操作。
在一个程序运行时,程序会专门为参数开辟一个内存空间,称为“栈”。栈所在内存空间位于内存的低地址区。当程序需要传递参数时,将一个个参数“压入”栈区内存的底部,然后,函数再从栈区一个个读出参数。
如果一个函数需要返回值,那么调用者首先需要在栈区留出一个大小正好可以存储返回值的内存空间,然后再执行参数的入栈操作。大都数编译器采用“从右到左的次序”将参数一个个压入。因此先将b压栈,再将a压栈。以下面这个程序为例。
//skk_Argument Passing.cpp
#include <iostream>
using namespace std;
int f(int a, int& b)
{
a++;
b++;
return 1;
}
int main()
{
int a=4;
int b=7;
int c(0);
c=f(a,b);
cout<<a<<" "<<b<<" "<<c<<endl;
return 0;
}
参数a是传值,参数b是传址。
很容易看出最后的结果是:
4 8 1
还有一种形式:
void swap (int *a, int *b);
我不太赞成用这种形式(虽然很多时候很有用),最好用
void swap (int &a, int &b);
这是因为使用前一种形式容易出现问题,例如在skk_Argument Passing.cpp加入以下这2个程序段:
void swap1(int *a, int *b)
{
int i;
i=*a;
*a=*b;
*b=i;
}
void swap2(int *a, int *b)
{
int *i;
i=a;
a=b;
b=i;
}
swap1可以起到交换a,b的作用。swap2就不行了。因为本质上来说它们仍然是值传递,只不过这个值是地址,它们都不能改变自己参数本身(指针a和指针b)。swap2完全是一个传值调用。swap1虽然不能改变参数,但是指针太危险了,它间接改变了指针指向int 。因此在这种情况下,我们声明成:
void swap3 (int &a, int &b);
这就告诉该函数有可能改变传递来的变量的值。但是最好在调用的时候在后面注释,因为调用的时候是看不出的,例如调用swap1的时候为swap1 (&a,&b)可以很好给读程序的人提示信息,告诉我们参数可能被修改。调用swap3的时候就是swap3(a,b),无法给出信息,所以最好给注释。即便这样,我仍然偏爱swap3的写法。不过对非const引用参数是不允许做类型转换的,如果可以,那么这样做会毫无意义。因为类型转换的时候需要临时变量