该程序以递归方式调用函数tester
。
#include <iostream>
void tester();
int i = 1;
int k = 1;
int main() {
tester();
}
void tester() {
while(i++ < 10)
tester();
std::cout << "called " << k++ << " times" << std::endl;
}
我对此输出感到惊讶:
called 1 times
called 2 times
called 3 times
called 4 times
called 5 times
called 6 times
called 7 times
called 8 times
called 9 times
called 10 times
这是因为这是我理解这个程序的方式:
首次从主调用测试人员后,它进入循环。循环的第一个语句再次调用函数tester
,并继续执行。循环10次后,while循环之后的语句应该,即只有一次。所以输出应该是:called 1 times
。但这实际上并没有发生!为什么?该计划如何运作?
答案 0 :(得分:2)
while
正文在每个递归深度中只执行一次。当while
为i
时,10
为false,这将是递归调用tester ()
10次的时间。由于i
已声明为全局,i++
每次调用都会显示tester ()
更新。
在while
条件为false时的最后一个递归深度,最后一次tester ()
调用将返回其先前的深度。此时,while
循环的下一次迭代将为false,因为i
为10
。在每个cout
循环终止后将遇到while
语句,它将依次打印k
的值,在递归回滚时递增每个递归深度。
手动追踪会发生什么事情来理解这些东西。
<强>更新强>
查看执行输出。特别要注意d
参数,它表示递归深度。在每个深度,while
循环迭代一次,直到最后“,而为真,测试人员称为”输出。在深度10处,while
为假,因为它是10,并且第一次将控件返回到其先前的深度级别(i
为10
时的第一次“返回” )。返回后,控件返回到最后一级的while
循环的主体,从中调用该函数(刚从中返回),并且该循环的下一次迭代将为false,(i是全局和10或更多),因此这也返回。类似地,在每个递归深度处,while
循环的第二次迭代为假,并且它一直返回。检查输出。
i k d 1 1 0, call from main 2 1 1, while is true, tester called 3 1 2, while is true, tester called 4 1 3, while is true, tester called 5 1 4, while is true, tester called 6 1 5, while is true, tester called 7 1 6, while is true, tester called 8 1 7, while is true, tester called 9 1 8, while is true, tester called 10 1 9, while is true, tester called 11 1 10, returning back, print k // this step the while is false in depth 10 12 2 9, returning back, print k // from now on, as the recursion rolls back 13 3 8, returning back, print k // the second iteration at each recursive 14 4 7, returning back, print k // depth will be executed, and each while 15 5 6, returning back, print k // condition will be false, therefore it will 16 6 5, returning back, print k // not call tester anymore and return the control 17 7 4, returning back, print k // to the previous level. NOICE the `d' parameter 18 8 3, returning back, print k 19 9 2, returning back, print k 20 10 1, returning back, print k
这是测试代码。我希望现在描述清楚(?)。分析这将有所帮助。
#include <stdio.h>
int i = 1;
int k = 1;
void tester (int d)
{
while (i++ < 10)
{
printf ("%2d %2d %2d, while is true, tester called\n", i, k, d);
tester (d+1);
}
printf ("%2d %2d %2d, returning back, print k\n", i, k++, d);
}
int main (void)
{
int depth = 0;
printf ("i k d\n");
printf ("%2d %2d %2d, call from main\n", i, k, depth);
tester (depth + 1);
return 0;
}
答案 1 :(得分:2)
由于递归,测试者的最后一次调用首先返回,因此打印顺序实际上与调用顺序相反。
编辑: 尝试这个代码,也许它可以帮助你理解(对不起,它不是很漂亮,只是快速破解):
#include <iostream>
void tester();
void print_indent(int cnt);
int i = 1;
int k = 1;
int recursion_level = 0;
int call_num = 0;
int main() {
tester();
}
void tester() {
int my_call = call_num++;
print_indent(recursion_level);
std::cout << "start of tester " << my_call << std::endl;
recursion_level++;
while(i++ < 10)
tester();
print_indent(recursion_level);
std::cout << "called " << k++ << " times" << std::endl;
recursion_level--;
print_indent(recursion_level);
std::cout << "end of tester " << my_call << std::endl;
}
void print_indent(int cnt) {
for (int i = 0; i < cnt; i++)
std::cout << " ";
}
答案 2 :(得分:1)
一旦启动递归调用 ,当前函数将冻结,直到该调用返回 。所以你的函数首先进行递归调用,然后打印。
所以第一次打印将在名为latest的函数中出现。一旦最新的被叫函数打印 并返回 ,所有先前的调用将开始打印并返回,直到最早的被调用函数退出。
答案 3 :(得分:1)
这是递归的本质。当tester()
调用自身时,它会构建一堆调用,然后在每个函数返回时打印消息。每次测试人员返回时,都会打印消息,由于while循环,该消息将发生10次。
我把它想象成这样:
i k
--- --- ---
1 1 + tester()
2 1 | + tester()
3 1 | | + tester()
4 1 | | | + tester()
5 1 | | | | + tester()
6 1 | | | | | + tester()
7 1 | | | | | | + tester()
8 1 | | | | | | | + tester()
9 1 | | | | | | | | + tester()
10 1 | | | | | | | | | + tester()
11 1 | | | | | | | | | + "called 1 times"
12 2 | | | | | | | | + "called "2" times"
13 3 | | | | | | | + "called 3 times"
14 4 | | | | | | + "called 4 times"
15 5 | | | | | + "called 5 times"
16 6 | | | | + "called 6 times"
17 7 | | | + "called 7 times"
18 8 | | + "called 8 times"
19 9 | + "called 9 times"
20 10 + "called 10 times"