00:00
下面呢,我们来给各位同学介绍一下函数的调用机制,也就是说我们来看一看函数,在在我们调用一个函数的时候,我们计算机它到底发生了什么事情,我们先给大家讲一个通俗易懂的一种理解方式,大家可以这样理解。哎,就好像这这有一个这是拉丁,拉丁给特工小组下达一个命令,把这个白宫给炸了。那么特工小组把这个任务完成以后呢?给他返回一个结果是炸成功了还是没有炸成功对不对?当然也有可能特工小组没有任何返回,为什么呢?被。被被美国把他抓起来了是不是,所以说你可以这样理解,就好像我们一个程序员去调用一个方法或者是一个函数,那么这个函数或者是方法呢,把这个结果给我们返回来,就可以这样去理解。那讲完这一个通俗易懂的版本呢?我们再来给大家用示意图的方式来画一下我们这个函数到底是怎么调用起来的,我跟大家举一个例子。
01:09
第一个例子呢,是传入一个数,把这个数加一对,就是传入一个数,把这个数加一,就完成这么一件事情,那么这个呢叫test函数,我们取个叫test函数,还有一个呢,就是计算两个数的和并返回,这个呢又是另外一个函数对一个叫get上。那么现在呢,我们来针对这一个题画出它的示意图,也就是说我们看看计算机它这个运行的这个机制,就函数的运行机制是什么样子的,那同学们我们打开这个代码哈,我们来运行一下,我先把前面不需要的东西呢,先给它注销一下好不好,先注销一下现在我们来写函数的一个机制问题。好,现在呢,我们取个名字叫function。
02:01
零二。好吧,或者叫function的一个原理。SH原理。那现在呢?我们include std。对VO的主函数。贸易的主函数,那下面呢,我们来写一个函数叫test。对,那这个我们先做一点说明哈,我们来做一点说明。第一点,函数的名字。函数的名字为test。这个大家看到没有,那么函数的返回值。没有。没有这个返回值函数没有返回。函数没有返回呢,然后呢,我们是用的void。能理解,然后现在呢,我们要接收一个数,好,我现在呢接收一个N,然后他说了这个T的函数的作用是传入一个数,把这个数加一。
03:05
是不是这个相当于说他要完成的功能是。完成。工人。是什么呢?完成功能。是这个字。好的,现在我们拿这个,拿到这个呢,我们把这个值加一并输出,比如说现在我用一个变量来接收它。对,比如说我有一个变量叫N2等于N加一对,然后呢,我们输出这一个N加一过后的结果就是number。输出N2。好,同学们,现在呢,这个代码其实挺简单的,我主要是通过这个地方呢,要讲解一下它到底是怎么跑起来的,好,我在这里呢,来给大家测试一下,比如说我test,我在这里写个变量叫number。等于六没问题吧,然后呢,我在这里调用我们的这个函数,我把这个number传进去。
04:05
然后呢,我给大家运行一下这个代码,这个代码显然它会输出N2等于几呢?N2等于七。来,我们预习一下是不是这样子的。好,我们运行这个结果,看一下同学们。是不是N2等于七啊。那到底为什么,它是到底为什么说出了这句话呢?来,同学们,现在呢,我们重点就是要画出这个示意图,帮助同学们理解函数的调用过程。那现在呢,我把这段代码先给各位朋友把拿到这边来,我们来详细的介绍一下。我们来详细的介绍一下,放这了啊,那现在呢,为了好看,我们把这个字体稍微放大一点。没问题吧,同学们,那现在呢,怎么来理解这个函数的调用机制,这一点尤其重要,注意听哈,这个我们就讲一次,叫函数。
05:01
函数的调用调用机制。函数的调用机制,我把这个呢,稍微放大一点,能理解哈,那现在我们来看到底是怎么做的呢?我先画一个内存。比如说这是我们的一个计算机的内存。计算机内存。对。那么这个计算机内存它怎么开始执行的呢?首先可以看到它在执行的过程中,第一句话他先执行了。Int number等于六,那么这句话在我们计算机内存会发生一件什么事情呢?来,同学们可以注意听哈,这点尤为重要。在计算机里面呢,有一个空间。有一个空间,这个空间呢,我们把它称之为占。注意听,这个叫赞。对,在我们计算机编程领域,把这个空间叫做占。
06:03
当当我们这个程序执行到主函数的时候呢,它会在这里开辟一个独立的空间,注意我说的是独立的空间,认真听。那在这个空间呢,我们姑且因为它这个是main函数,所以说呢,我们把这个站呢,可以称之为叫main站。能理解哈,在这个main站里面呢,它执行了一个叫number等于number等于六的动作,那么就相当于在这个站里边呢,它有一个number变量,这个变量。的值是多少呢?16。也就是说,当我们执行完这句话过后呢,你可以认为在站里面有一个number变量,它的值为六,紧接着呢,它调用了下一句话叫做test number6好,这句话关键来了,它会发生什么事情呢?当我们的代码执行到test number的时候,注意听,注意听好。
07:00
当他执行到test number的时候呢,它会开辟另外一个站。在上边儿。这个赞呢?我们可以给它取个名字叫泰森,也就是说他他一执行到这呢,代码就噌得下跑这来了。这点大家要深刻的理解,也就是说,当我们执行到一个test的函数时,我们的代码就会执行到test函数,而在执行到一个函数的时候呢,它会开辟另外一个独立的空间,叫test站。这是一个独立的空间,这个太站里面大家可以看到这有个行参叫int,那么同学们可以看到你在。Test的时候,这个number是不是等于六,你可以理解成test的地方传了一个六进去,把这个六传给了谁呢?传给了这个。N,那也就是说在我们这个T的站里面呢,会有一个新的数据变量叫N,它的值呢,就是你这传进来的六理解了吗。
08:06
这点很重要。这点是特别重要,也就是说我们程序一旦执行到这儿的时候。执行到开始的时候呢,其实他开辟了一个新的站。你可以这么理解。就好像到这来执行这个站,那这个时候呢,因为你这个number等于六,所以它会把这个六呢,传给我们这个test站的这个行参N,这个行参N在哪里呢?就在我们test这个函数里面,也可以理解成是在test站里面,紧接着呢,他又去创建了或者叫定义了一个新的变量叫N2 N2等于N加一,于是在我们这里面呢,又产生新的一个变量叫N2,这个N2的值是什么呢?是N加一,各位,N现在是不是等于六加一就变成七了,换言之,这个就是七。那么执行完这句话过后,是不是他在这个这个站里面,他去执行一个print什么什么什么什么。
09:05
大家看到这个print是不是打印出N2的值啊?那N2的直线是不是七,所以说你可以想象在我们的这一个控制台,你可以理解这是控制台,在这个控制台里面,它会输出一个N2等于多少的值N2。等于多少呢?就等于七了。他就这么来了,但是问题来了,当我们这个地方执行完的时候,大家可以看到这个函数就执行完毕了,因为print是我们这个test函数的。最后一句话,当他把这句话执行完毕过后,他会怎么办呢?同学们?那么他就会重新返回到这个位置,也就是说我们可以认为他把这句话执行完了过后呢,又回到了我们这个位置。我同样用这个绿色线表示。诶,这个。
10:03
这个线。把它支支顶炮。诶,这个线呃,回不来啊,不好看了,那这样子我。我这样画。好,这样子应该大家看清楚了哈,这样看大家看清楚了,我换一个这样的线,也就是说当我们把这一个test函数的最后这条语句执行完毕过后呢,这个语句会重新回到返回到这个调用的位置。那调用的位置这个地方有一个get叉,它会停在这里。它就停在这,也就是它会返回来,能理解了吧,这个就是我们整个函数的一个调用机制,大家看懂了吗?那当然了,有同学可能问说老师他一返回这个还有没有呢,你可以认为哈,一旦返回的话呢,这个站你可以认为这个也就没有了。
11:02
你可以认为哈,你可以认为因因为他用完了嘛,你可以认为这个站呢,就销毁了。好,同学们,老师把刚才的这一个流程用几句话给大家整理一下,这这几点很重要,听,注意听哈,我写到这里。函数调用。调用。调用的规则。一。当当调用或者叫执行,当调用或者这个也可以叫执行,执行一个函数时。当调用或者执行一个函数时,就会就会开地开。开辟一个独立独立的空间。好,这个空间呢,我们把它称之为占。大家看清楚没有,就是刚才这样的一句话,这是第一句话,第二句话呢,每个每个占空间,占空间是相互独立的。
12:03
为什么说相互的,你看你把这个number传进来,这边的NN2跟你的这个number并不冲突。并不冲突,也就是说你这个命站里面的number在这个空间里边,你这个太站里面的N和N2在这个站里边,大家呢,不冲突,就好像两个两个教室一样,这个是A教室。这个呢,是B教室,他们两个并不冲突,明白这个意思吧。第三点,注意听这句话。第三点第三点当当函数执行完毕后,完毕后。啊,会返回返回到调用。调用函数的位置。位置继续执行。这点尤为重要,也就是说当我们这个函这个这个函数调用执行完毕以后呢,它会回到原先这个调用的位置,继续往下执行。
13:03
那同学们可以试一下,假如说我们在这面。在这边说出一句话。OKOK,那我问大家一个问题。那么我问大家问题,这句话,先输出还是OKOK,先输出。是不是根据我们原先的理解,当它执行到这个test的时候,他会到这边来,他在把这边代码执行完毕,执行完毕过后呢,他又回到这个位置,是不是继续往下执行,因此它应该输出N2等于一个七,然后再输出OOKOK这样一句话。是不是这样子的呢,我们来运行一下。我们执行这个结果,我们可以看一下,的确跟我们分析的完全一样,大家看这是不是N2打了个OKOK,因为我这没换行,大家可以可能感觉不到哈,或者换一行,同样这上面呢,我们也换一行,这样看起来会比较清晰一点,走起来。我们运行一下怎么看。
14:01
当我们运行完毕过后呢,你会发现的确这样子的。好,这就是我们讲的这个函数调用的一个示意图,非常的重要,这个很重要啊,同学们,这个我刚才这讲的很重要,虽然它不难,但是确实很重要,我们再来看一个。计算两个数并返回这个结果,那这次呢,我们再来给大家举个例子来,同学们。下再来写,这个时候呢叫盖上。我们传进去一个N1,再传进去一个N2。然后呢,我怎么做呢,我这样子来执行,同学们,我N1加N2的这个和。也可以这样写,大家看这面是错,错误原因是因为我这没有写返回变量,这样也可以。那这个时候呢,我们也可以再来这样玩一把,比如说我用一个res的接收,我这样写也是可以的,怎么样呢,我直接调用这个get sum给他传一个一再传一个九。
15:03
那么我问同学们一个问题。这个时候。这个时候我输出RS,它应该等于多少呢?它应该等于多少,显然是等于N1加N2的这个和,也就是说这边应该输出十,是不是这样子的呢?我们来执行一下。我们可以看到res的确等于十啊,这个没换行啊,我们还是换一行输出,这样看起来呢,会比较清晰一点再来。跑起来。跑起来过后呢,我们发现的确这样子,R等于四。那我们同样也来针对这个代码,再来分析一下get上是怎么执行的。对,其实它跟刚才那个执行的流程一样,只是呢,我给,只是这次他有返回值了,我们再来给大家看一下此时此刻是怎么执行的,来,我把这句话呢又拉过来,好。这句话拿过来过后呢,我们在下面再来分析一把,对,我们就分析两次,同样我们先插进去一段代码。
16:06
好,这个代码呢,为了好看,我给它来一个填充颜色。灰色的。好,然后呢,这边仍然是我们的这个计算机内存,我拉过来。好,大家看到我的思路就开始了,代码从哪里开始执行呢?显然是从这个地方开始执行啊,就说我我我们把这个跟跟这个有关的我们先不要了哈,这个我就去掉了,明白这意思吧,因为我只看跟干上相关的这个结果,好,我们现在开始玩还是老规矩,首先呢,在计算机内存,内存里面呢,有一个占空间,这个刚才我们已经说过了。当我们整个这个执行刚开始执行到命的时候呢,这个地方会有一个独立的命在。我把它吸到这里。认真听哈,这个我们可以认为是个命。AI命站在这个站里边呢,同学们看他上来过后就执行了一个RS等于get上,然后呢,这边传了一个九和一个。
17:11
一一和九,我问同学们一个问题。此时此刻,根据我们原先讲的规则,它现在是不是调一个函数了,调一个函数是不是就会该一个独立的站呢?是不是在这有个独立站,这个站呢?我们取这个名字就叫get some。那我问大家在这个站里边。就是在同学们看到这个干上这个站里面是不是得到了一个一和九,而这个一和九是被谁接收的,大家看一下这个一。是不是给到了N1。而这个九给到了N2,能看明白吗?那这样子的话,就意味着在我们这个概率上,这个站里面有个N1这个变量,那么这个变量空间面放的是一,还有一个N2这个变量,这个里面放的是几呢?显然放的是九,为什么放的是九,你传的是九啊。
18:00
紧接着当然它这个已经到这来了啊,到这来过后呢,它就执行了一个return语,看这里N1加N2,我问大家N1加N2实际上就是一加九,换言之可以理解成就是瑞成一个十。那我问大家一个问题,你在调的时候,实际上是到这儿来了。对吧,你在调用的时候,你到这个站来了,那你这个地方遇到一个。这个语句会返回到哪里呢?返回到我不是讲过吗?哪里调用就返回到哪里。是不是相当于返回到?该成上面这个位置,也就是说你可以理解理解成这个返回的值替换了它。这样大家是不是就明白了?为什么?刚才我不是讲过吗,就是。函数执行完毕后,会返回到调用函数的位置继续执行,那这个时候它返回不但是简简单单返回,而且还返回一个具体的值十,那这个十就会给到哪里呢?
19:00
就会给到这个result,也就是说这句话你可以理解成返回了一个十。那返回一个十的话,RS肯定到这个地方,R就等于这个十了。然后你这边执行完了,是不是你返回到这边,然后你就输出RS,你在这面是不是执行了一句话叫做print。什么呀,Res这个结果,显然这一段就应该输出十。就这么来的。好,这个是不是跟前面我们说的函数调用的规则完全一样,仅仅跟原先不一样的是有返回值,所以说我在这补一句话,返回到继续执行,如果有返回值。注意听,如果函数有返回值,返回值则则,则干什么将这个返回值赋给接收的这个变量,则将。返回值返回值付给付给接收的变量接收。
20:04
接收的变量,我问大家哪个是接收的变量?你这方哪个是res,是不是接受变量,那就相当于说把。把这个。哎,这人上哪去了?相当说将这个返回值赋给了接收变量RS,当然这样子一返回过后呢,我们这个站也就销毁了。您可以这样理解哈,我们可以再加一句话,就是一旦返回呢,我们上面那个站也就销毁了,行了。好,一旦返回,当一个函数返回后,返回后。该函数,该函数对应的占空间,占空间也就也就销毁。能理解了吧?哎,其实这几点是不是对我们去理解这个函数的调用规则特别的重要。后面我们再去做函数调用的时候,这个规则是一直要遵守的。
21:02
不管你学的是C语言,还是Java语言,还是其他编程语言,这些规则都是统一的,也就是说这个规则是适用于适用。适用于其他语言,比适用于加Y呀,或者是C加加呀,或者是咱们的PHP等。等等,好,各位同学,那关于这一个函数的调用过程很重要,我就讲完了。那瑞语句是不是刚才已经顺带的讲完了?这个维表示什么?将返回的这个值返回给接收者,就是刚才我讲的这句话吗?如果有返回值,这个return就表示有返回值吗?返回给接收的变量。但是有些同学说了,说老师假如我这儿没有接受变量呢。那相当于说没人接收。相当于说你返回了一个值,但是没人接收,那没人接收就没人接收嘛,就好像呃,打个比方,你去呃,你去嗯,给你去买了一个包子,这个包子是给张三的,结果张三说我张三说我不要这个包子了,那你就留着呗,相当于说没人接收了,这个也无所谓好,这个也无所谓好,那么这块就讲完了,那么我们再来看看这里面几句话,再把它过一下。
22:18
同学们看,嗯,语句是其实已经讲过了,说几句话,如果没有返回值要求把这个返回类型写成贸易的,好,这个地方有点这个,嗯,下面颜色有点看不清楚,我把这个颜色稍微替换一下哈。对,如果没有返回值,返回类型需要写成VO的。贸易的表示我没有接收,如果有返回值呢?返回的类型要明确。要求返回值和返回类型要匹配,或者可以相互转换。可以是自动转换或者是强制转换,我把第二点给同学们稍微的描述一下,举个例子。举个例子,你比如说同学们看这个案例,还是以这个案例为主,大家看我们在这里是不是反,这个是N1加N2,是个int返回给他,这个类型是匹配的。
23:10
但是你不是说我我这边返回的是另外一个类型,我瞎写,比如说我写个贸易的。那你写个VO的这个就不对了,因为人家返回的是个int。但是呢,你学习和贸易的类型不匹配。明白,所以你要写个才可以。对,那再比如说打个比方,你你返回你这边接收者是是一个硬的,但是你返回的是double,这方也也要小心,比如说我这样写一个,大家看他会给一个警告的1.0。各位,如果我这样去写的话呢,大家知道N1加N2加1.3是呃11.0,是不是整个这个结果是个W型。而这边接收者是一个什么类型,各位同学是一个类型,相当于说你现在就相当于把一个double。
24:00
不会给一个in特,那么我问同学们,假如我们生成解决方案,是不是他会给一个警告啊,我们看是不是给一个警告来看。各位,这个时候呢,他会给一个警告,我们看编译会不会在这一行给出一个警告。好,我们往下看。好的,可以看,的确在这方写出一个警告,看,就这这句话。他说从double转成int可能丢失数据,但是如果说说老师,那我不管那么多,我就要强制转换,这是可以的,比如说你转成一个int,把后面这一大节全部整体转成特,你再生成就不会有这个警告了。那我们再来生成一下。好,这次呢,就不会,应该已经没有任何警告了。大家看是不是这样子,你看一句都没有了。没有吧,所以说这句话的意思呢,就要这么去理解,什么叫如果有返回值,返回值的类型一定要明确要求返回值和返回类型要匹配,要么是自动转换,要么是强制转换。
25:01
你看刚才我这边就用的是强制转换,自动转换指的什么意思呢?如果说这样子,你就不要说啊,这是个double。这是大部,然后呢,各位看。各位看这样写是不是就是对应的这个,这个是个double,这个也是个double,那么如果我把1.0去掉,请问。他会给警告吗?也不会给警告,因为你这个N1加N2是int。是int类型,然后呢,你把这个int返回给给一个double,这个是可以的,因为你是从低精度向高精度,会有一个自动转换功能。对不对,自动转换。A、自动自动转换。自动。自动转。这是可以的,那这个时候你会发现呢,虽然这两个类型不匹配,一个是英特尔,一个是double,但是因为它是自动转换,仍然不会有任何的警告,来看一下。
26:01
大家可以看到是不是没有任何广告,没没有警告吧,你看。诶。它是从double到int。从double到int。好,那这个警告应该不是这个地方的问题了,而是接收的问题了。应该是这。是不是这个地方有有问题,因为你整个这个返回的是一个什么类型,各位同学。这个是不是返回给double,他的警告应该是在这一行产生的。这是个double给到英特了,所以说不,不是我们这的问题啊,不是我们这的这的问题,你看如果我把这下面这句话注销了,这个就不应该有任何的警告。那这个地方不会有,是不是没有任何警告啊。是不是没有任何警告?没有吧,那刚才为什么有警告呢?是因为是因为你这个地方的问题,这个地方的问题,这个地方你是这个地方是返回了一个double,因为你这不是讲了吗,这个return完了过后,这是return的一个return的一个int,但是呢,返回了一些double。
27:01
它相当于说这个返回这是个int转成了一个double,然后呢,这个当然就是就是一个double了,也就是说你返回的类型到底是以哪个为准为以这个为准。而不是以这个为准,看到没有。因为他的流程实际上是先把这个结果转成你的这个类型,然后再把这个类型呢返回给我们这个结果,然后再把这个结果呢给到这个,Re,这个时候就出现问题了,因为你这个是double给到int不行,除非你怎么改呢,说老师我把这个改成double,这就没问题了。好,这样就没问题,你看当然这个大包我们这样输出的话呢,就2F这样,这样就不会报错。也不会给任何警告。看一下。哎,这地方都是小细节喽,小细节有时候是蛮重要的,你看没有任何警告。是不是好的同学们,那关于这一点我们也就说到这里,例子呢,就是刚才举的一个例子,好,同学们,我们先来把我们现在呢,就把函数的一个调用机制给大家做了一个详细的介绍,大家看看能否理解,一定要深刻理解哦,同学们,尤其是我们画的这一个图,还有这个图以及老师跟大家整理的函数的调用规则尤其重要。
28:19
尤其重要,一定要认真领会好各位同学,那关于函数的调用机制,就给同学们先讲解到这里。
我来说两句