Day 05 2020.08.30 函数基础 传值、传址、传引用

没补作业!!昨天看完了第三章:函数的基础

但英雄联盟比赛开始了,哎~

自古鱼和熊掌不可兼得,但加班和穷可以!!!

后悔在一开始学习C++时没读到这本书,虽然现在可以熟练地使用函数声明、定义,但对于其中一些基础的东西一直不是很明白,但非要我说哪里不明白吧,还说不出来。就是觉得没有系统地学习过,感觉心虚。今天系统的学习了这部分后,我还是说不上来我又学到了什么。。。但是就是觉得莫名的心安。(揣测了一下,应该是地基不牢,所以总害怕自己盖得房子会倒的那种感觉)

声明一个函数的方式,形如   int 2Sum(int x,int y); ,就是函数的定义。

1.第一个int 声明了该函数的返回值类型,当然也可以是double、char 、和void(表示无返回值)

2. 2sum 为声明的函数名,一般用来描述该函数的作用可以使程序可读性强一点,当然命名为A、B、C、D也行,但不建议~

3. x、y为函数的输入,函数的输入个数由自己定义,需要几个定义几个,x、y前面的int表示输入变量的数据类型,也由我们自己根据要实现的功能定义。

4.声明函数结尾处的“ ;”别忘记

定义函数的方式

int 2Sum(int x,int y)
{
int z=0;
z = x + y;
return z;//2Sum函数声明为int型,返回值也要是int型
}

说白了就是在大括号内写下自己期望的对输入数据的操作,并根据预先的定义类型,返回对应的输出。

函数调用:

int sun;
int a = 1;
int b = 2;
sum = 2Sum(a,b);//这里涉及到函数的参数传递,这里采用的是传值,而不是传址

函数参数传递机制的基本理论   
    函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:传值、传址、传引用。

以下讨论称调用其他函数的函数为主调函数,被调用的函数为被调函数。

   
    传值:被调函数的形式参数(形参)作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形参的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。

         传址:是传值的一种特殊方式,只是他传递的是地址,不是普通的如int 。那么传地址以后,实参和形参都指向同一个对象

  
    传引用,被调函数的形参虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

为了说明这个问题看下面的程序:

#include <iostream>

void swap(int a,int b);//如果声明和定义在一个文件里,可以省略
/*
一般说来,我们会倾向于把函数的声明放在.h头文件里
在同名(不同名也行,但别给自己找麻烦好么)的.cpp文件里对其进行定义
.cpp需要引用.h头文件(#include"xxxx.h",自己定义的头文件用双引号编译环境提供的用<>)
然后在需要调用该函数的.cpp文件中,也加上#include"xxxx.h"
这样我们的main.cpp就可以简化许多,要不然没实现几个小功能函数
main.cpp就要几百几千行了...
*/

int main()
{
	int x = 5, y = 6;

	swap_value(x,y);//不是将x,y交换,而是将5 和6交换了,这就是传值
	std::cout<<"传值后x,y分别为"<<x<<"、"<<y<<std::endl;//这里的输出是5、6而不是6、5

    swap_address(&x,&y)交换了x,y的地址,& 取地址符
    std::cout<<"传址后x,y分别为"<<x<<"、"<<y<<std::endl;

    swap_reference(x,y);
    std::cout<<"传引用后x,y分别为"<<x<<"、"<<y<<std::endl;

	return 0;
}

void swap_value(int a, int b)//传值,交换两个输入
{
	int temp;
	temp = a;
	a = b;
	b = temp;
}

void swap_address(int *a, int *b)//传址,交换两个输入
{
	int temp;
	temp = *a;
	*a = *b;
	*b = temp;
}
void swap_reference(int &x, int &y)//传引用,交换两个输入
{
	int temp = x;
	x = y;
	y = temp;
}

执行swap_value(x,y)时,swap_value(int a, int b)形参a,b获得了x,y的拷贝。在swap_value函数中,a,b确实交换了。但a,b获取的是x,y的拷贝,x,y实质上并没有改变。函数调用完成后,a,b同时也结束生存周期。

执行swap_address(x,y)时,swap_address(int a, int b)形参*a,*b获得了x,y地址的拷贝。在swap_address函数中,*a和*b进行交换。虽然也是交换拷贝的内容,但此时改变的是地址,而这个地址就是x,y的地址,也就实现了x,y的互换。形参只是一个指针,它指向的是已经在其他地方分配好内存的空间。

传引用调用过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的参数变量;
引用传递方式是在函数定义时在形参前面加上引用运算符‘&’。在函数被调用时,参数传递的内容不是实参的值,而是实参的地址,即将实参的地址放到C++为形参分配的内存空间中,因此形参的任何操作都会改变相应实参的值。

一般而言,传址比传值效率高。因为传值对整个类型进行了拷贝,而传址只复制了地址。比如,现有一个结构体,存储了大量的数据。传值拷贝了整个结构体,而传址只是拷贝了地址。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值