函数返回值与参数传递

时间秒杀一切 提交于 2019-12-19 10:00:02

1.函数返回值基本理解
函数返回的不管是指针还是数值,通常,函数将返回值复制到指定的CPU寄存器或内存单元中来将其返回。随后,调用程序将查看内存单元。返回函数与调用函数必须就该内存单元中存储的数据的类型达成一致。函数原型将返回值类型告知调用函数,而函数定义告知被调用函数应返回什么类型的数据。在原型中提供与定义中相同的信息似乎有些多余,但这样做确实有道理。要让信差从办公室的办公桌上取走一些物品,则向信差和办公室中的同事交代自己的意图,将提高信差顺利完成这项工作的概率。由此可知函数原型的重要性,返回值类型,参数类型,参数个数信息。

2.函数返回值深入理解
函数的返回值是放在一个临时的内存单元,理解到这一点很重要。如果被调用函数内部创建一个局部变量,但是返回的是也是这个局部变量。那么首先被调用函数将这个局部变量的值复制到临时的内存单元,接着,被调用函数彻底返回,而被调用函数中的局部变量也被销毁,内存丢失,数据丢失,但是我们已经将其值拷贝到另一个内存单元中,所以调用函数去这个临时内存单元可以取到函数返回值。如果被调用函数内部创建一个局部内存块,比如数组,返回的是数组名,也即数组第一个元素的地址。那么过程与上述类似,被调用函数将这个地址放到一个临时内存单元,最终返回给调用函数,调用函数去临时内存单元中取这个地址,到这里都是没有问题。接下来,当调用函数通过这个地址去访问地址中的内容时,oops,因为该地址指向的内存单元已经被销毁,因为它是局部的内存单元,所以访问出错。如果该内存是malloc分配的,返回指向它的局部指针,这样就是没问题的,因为返回后,内存单元仍然存在,所以返回的地址也是实际存在的,访问正常。如果返回的是局部变量的引用,则与指针效果一样,局部变量内存单元被销毁后,引用的又是什么呢?

3.实例演示
struct free_throws {
int value;
}
free_throws dup;
free_throws team;
free_throws & value;
free_throws & accumulate(free_throws & owner)
{
owner.value = 1;
return owner;
}

dup = accumulate(team);
value = accumulate(team);

类型匹配的情况下,参数传递的过程是:
1.accumute定义并初始化一个临时引用,free_throws & owner = team;可知,局部引用owner指向team,注意这里,是没有拷贝的,这个赋值,只是让owner成为了team的一个别名,也就是引用了team,如果是free_throws owner = team,注意这里将产生一次拷贝,把team结构体拷贝到owner结构体中。最后返回owner,也即返回team的引用,因为team内存单元一直存在,所以该局部引用返回后是生效的。如果返回的是一个结构,而不是该结构的引用,将按第1节描述的一样,将返回值复制到临时位置,再将这个临时位置的值拷贝到dup,所以这里其实有2次拷贝。但是这里返回的是引用,那么将直接将team复制到dup中
2.引用只能在在定义的时候初始化引用谁,后续的赋值,都将改变引用的值和被引用的值,而不会改变引用的变量是谁。

4.在函数传参类型不匹配的情况下,C++将生成临时变量,当前,仅当参数为const引用时,C++才允许这样做。
a. 实参的类型正确,但不是左值
b. 实参的类型不正确,但是可以转换为正确的类型
需要理解的一点时,指针与引用的区别,给指针传参,需要传指针相同的类型,比如
int *p;
int *a = &c;
a = p
但是引用传参时int &a = b; int b;注意到区别了吗?传递给a的是b,但是a已经成为b的引用,a的类型为int &,而b的类型是int,两个类型是不一样的。
所以如果team不是free_throws类型,那么C++是这样做的,首先创建一个无名的临时变量,并将其初始化为team的值,接着创建临时引用owner,但是owner被初始化该临时变量的引用。所以这里创建了两次临时变量,这个特性也是需要掌握的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!