所以我的一个朋友正在参加他的第一个CS课程,并提到他在他的第一个课程中使用递归。他发给我下面的代码。马上,我注意到他没有抓住他的递归调用的返回值,我认为它不起作用。但是他坚持认为它确实有效,所以我尝试了他的程序,令我惊讶的是它的功能完全符合预期。忽略这一事实,这是从A点到B点的愚蠢方式,为什么这甚至有效?
我正在玩他发给我的东西,并在if语句后添加cout
。除此之外,第一块代码和第二块相同。
如果我为第一个节目输入以下内容,这就是我得到的内容......
输入一个数字:10
您输入了:10这是正确的吗? (是/否):N
输入一个数字:12
您输入了:12这是正确的吗? (是/否):Y
main()= 12
然后,如果我对第二个程序做同样的事情,这就是我得到的......
输入一个数字:10
您输入了:10这是正确的吗? (是/否):N
输入一个数字:12
您输入了:12这是正确的吗? (是/否):Y
main()= 6300096
发生了什么事?!
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int getNum()
{
cout << "Enter a Number: ";
int x;
cin >> x;
cin.ignore(100, '\n');
while(x < 0) {
cout << "Please enter amount greater than 0: ";
cin >> x;
cin.ignore(100, '\n');
}
cout << "You entered: " << x << " Is this correct? (Y/N): ";
char response;
cin >> response;
cin.ignore(100, '\n');
if (response != 'Y') {
getNum();
} else {
return x;
}
}
int main() {
cout << "\nmain() = " << getNum() << endl;
return 0;
}
顶部和底部之间的唯一区别是if语句之后的cout
语句。
#include <iostream>
#include <cstring>
#include <cctype>
using namespace std;
int getNum()
{
cout << "Enter a Number: ";
int x;
cin >> x;
cin.ignore(100, '\n');
while(x < 0) {
cout << "Please enter amount greater than 0: ";
cin >> x;
cin.ignore(100, '\n');
}
cout << "You entered: " << x << " Is this correct? (Y/N): ";
char response;
cin >> response;
cin.ignore(100, '\n');
if (response != 'Y') {
getNum();
} else {
return x;
}
cout << "returning... " << x;
}
int main() {
cout << "\nmain() = " << getNum() << endl;
return 0;
}
答案 0 :(得分:6)
在机器代码级别,通常在特定的处理器寄存器中返回足够小的函数结果。
通过在return
的某些调用中不执行getNum
语句,正式代码具有未定义的行为,但可能会发生以下情况:
getNum()
被调用,用户回答N
。
getNum()
以递归方式调用,用户回答Y
。
getNum()
执行return x;
。使用典型的C ++实现,将返回值放在寄存器中,让它称之为R.
执行返回getNum()
(原始调用),现在通过函数结束执行返回,而不是return
。
调用代码按预期在寄存器R中找到值。
所以,它可以“起作用”。
但它是正式的Undefined Behavior,以及其他一些编译器和/或选项,它可能无效。
答案 1 :(得分:2)
在C ++中,编译器没有彻底检查函数是否在没有return语句的情况下结束其流程,因为检查所有控制路径并不容易。此代码的行为未定义,实际发生的内容取决于调用约定。
我认为他们在return
之前忘了getNum()
。它会工作并且不会污染堆栈,因为如果尾递归优化。
这个代码对于第一个CS类来说很奇怪。