我正在学习函数,通过引用调用和函数调用按值,我在发现为什么它会让我回到6561时遇到问题。
在我的main函数中,我调用了一个函数f(p,p)
,其中p在调用之前被初始化为5.
我将函数f定义为:
int f(int &x, int c)
{
c = c - 1;
if (c == 0)
return 1;
x = x + 1;
return f(x,c)*x;
}
为什么此代码会返回 6561
?
答案 0 :(得分:3)
这个函数是一个相当复杂的函数来学习引用,因为要理解作为引用传递的第一个参数的含义,首先需要理解递归的本质。
让我重复你的代码:
int f(int &x, int c)
{
c = c - 1;
if (c == 0)
return 1;
x = x + 1;
return f(x,c)*x;
}
显然在某个地方有另一个函数包含这样的代码:
int p = 5;
result = f(p, p);
首先要注意的是它是递归调用自己的事实。
参数c用作计数器以限制递归调用的数量。它在f()
的第一行递减,当递减到0
时,递归停止(仅返回1
)。
由于p
初始化为5,递归将在5次调用后终止。
在f()
的第4行,参数x递增。
最后在最后一行中,递归调用传递了x的引用和递减的c。
显然函数返回6561作为结果,即9 * 9 * 9 * 9(相当于9 * 9 * 9 * 9 * 1)。这是对这里发生的事情的暗示。
让我们通过递归来跟踪数据:
#0:条目:x = 5,c = 5,就在最后一行之前:x = 6,x = 4
#1:条目:x = 6,c = 4,就在最后一行之前:x = 7,x = 3
#2:entry:x = 7,c = 3,就在最后一行之前:x = 8,x = 2
#3:entry:x = 8,c = 2,就在最后一行之前:x = 9,x = 1
#4:条目:x = 9,c = 1,就在第3行之前:x = 9,x = 0(在第3行返回,返回1;)
使用return 1
不再进行递归调用。现在我们通过递归向后返回:
#3:x = 9 =>返回1 * 9; (评估为9)
#2:x = 9 =>返回9 * 9; (评估为81)
#1:x = 9 =>返回81 * 9; (评估为729)
#0:x = 9 =>返回729 * 9; (评估为6561)
现在为什么在所有四个递归级别中x = 9?因为它是作为引用传递的,而不是值。这意味着对于f()
的所有递归调用,x在内存中基本上是相同的变量(实际上所有x都是p的别名)。在从第一个递归级别返回之前不仅x = 9,在f()
返回后p将为9。
虽然您为两个参数传递p,但x在所有递归级别上都相同,而x不是(按值传递)。这应该解释不同之处。
如果您还不了解,请阅读有关参考文献的内容。如上所述,这个函数对于学习引用来说是一个相当复杂的函数,它似乎没有用处。