为什么这种递归在 C++ 中有效?
Why does this kind of recursion work in C++?
我制作了一个递归 C++ 程序,如下所示:
using namespace std;
#include <iostream>
bool recursive(int num)
{
if (num == 6)
{
return false;
}
else if (num > 6)
{
return true;
}
else
{
if (recursive(num + 1))
{
return true;
}
else
{
return false;
}
}
}
int main()
{
if (recursive(0))
{
cout << "Not found!" << endl;
}
else
{
cout << "Found..." << endl;
}
}
它有效,我认为这是(大致)最好的方法。
我的朋友做了一个更简单的递归程序,如下所示:
using namespace std;
#include <iostream>
bool recursive(int num)
{
if (num == 6)
{
return false;
}
else if (num > 6)
{
return true;
}
else
{
recursive(num + 1);
}
}
int main()
{
if (recursive(0))
{
cout << "Not found!" << endl;
}
else
{
cout << "Found..." << endl;
}
}
他的作品和我的一样,但我不明白为什么会这样。在我看来,他的 else 块中似乎没有返回任何内容,所以我不明白布尔值是如何返回到原始函数调用的。
出于好奇,我在JavaScript做了一个类似的程序:
function recursive(index)
{
if (index == 6)
{
return true;
}
else if (index > 6)
{
return false;
}
else
{
recursive(index + 1);
}
}
if (recursive(0))
{
console.log("found");
}
else
{
console.log("not found");
}
但是JavaScript程序不起作用,这让我觉得这是C++特有的。
为什么我朋友的程序可以运行?它是完全有效的,还是未定义的行为?
这是未定义的行为。由于函数被声明为 return 布尔值,它总是 return 一些东西,但不一定是正确的值。
如果您使用 -Wall
标志进行编译,GCC 等编译器会对此类代码发出警告。
为什么有效?答:没有。
else
{
recursive(num + 1);
}
您朋友的程序缺少 return
语句。
else
{
return recursive(num + 1);
}
不 return 从非 void
函数获取值会导致未定义的行为。
在这种情况下,碰巧在您测试的计算机上,递归调用的 return 值自动 "returned" 给调用者——也许是因为它恰好在正确的注册。这纯属偶然。你不能依赖它。在不同的机器上,或者不同的编译器,甚至不同的调用,程序也可能 return 其他东西,或者崩溃,或者做任何你能想象到的事情。
在没有 return 语句的情况下结束函数是 C++ 中的未定义行为。我能做的最好的事情就是 推测 发生了什么,我最好的猜测是对 recursive(index + 1)
的调用,是函数 [=15 之前堆栈中的最后一件事=]s,被选为 return 值。因此,在(非标准、不可移植、不建议一般使用)意义上,代码隐式插入了 return 语句。
当然可以!好吧,不是真的。
地球上的每个编译器(也许不是)都会警告您:
clang: control may reach end of non-void function
gcc: control reaches end of non-void function
MVSC: not all control paths return a value
它确实 有效,因为您的朋友很幸运没有让这个程序爆炸、内爆或在您的卧室里制造黑洞。未定义行为就是这样:您无法判断您的程序将如何运行。
标准对此是这样说的:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main (3.6.1)
results in undefined behavior.
我制作了一个递归 C++ 程序,如下所示:
using namespace std;
#include <iostream>
bool recursive(int num)
{
if (num == 6)
{
return false;
}
else if (num > 6)
{
return true;
}
else
{
if (recursive(num + 1))
{
return true;
}
else
{
return false;
}
}
}
int main()
{
if (recursive(0))
{
cout << "Not found!" << endl;
}
else
{
cout << "Found..." << endl;
}
}
它有效,我认为这是(大致)最好的方法。
我的朋友做了一个更简单的递归程序,如下所示:
using namespace std;
#include <iostream>
bool recursive(int num)
{
if (num == 6)
{
return false;
}
else if (num > 6)
{
return true;
}
else
{
recursive(num + 1);
}
}
int main()
{
if (recursive(0))
{
cout << "Not found!" << endl;
}
else
{
cout << "Found..." << endl;
}
}
他的作品和我的一样,但我不明白为什么会这样。在我看来,他的 else 块中似乎没有返回任何内容,所以我不明白布尔值是如何返回到原始函数调用的。
出于好奇,我在JavaScript做了一个类似的程序:
function recursive(index)
{
if (index == 6)
{
return true;
}
else if (index > 6)
{
return false;
}
else
{
recursive(index + 1);
}
}
if (recursive(0))
{
console.log("found");
}
else
{
console.log("not found");
}
但是JavaScript程序不起作用,这让我觉得这是C++特有的。
为什么我朋友的程序可以运行?它是完全有效的,还是未定义的行为?
这是未定义的行为。由于函数被声明为 return 布尔值,它总是 return 一些东西,但不一定是正确的值。
如果您使用 -Wall
标志进行编译,GCC 等编译器会对此类代码发出警告。
为什么有效?答:没有。
else
{
recursive(num + 1);
}
您朋友的程序缺少 return
语句。
else
{
return recursive(num + 1);
}
不 return 从非 void
函数获取值会导致未定义的行为。
在这种情况下,碰巧在您测试的计算机上,递归调用的 return 值自动 "returned" 给调用者——也许是因为它恰好在正确的注册。这纯属偶然。你不能依赖它。在不同的机器上,或者不同的编译器,甚至不同的调用,程序也可能 return 其他东西,或者崩溃,或者做任何你能想象到的事情。
在没有 return 语句的情况下结束函数是 C++ 中的未定义行为。我能做的最好的事情就是 推测 发生了什么,我最好的猜测是对 recursive(index + 1)
的调用,是函数 [=15 之前堆栈中的最后一件事=]s,被选为 return 值。因此,在(非标准、不可移植、不建议一般使用)意义上,代码隐式插入了 return 语句。
当然可以!好吧,不是真的。
地球上的每个编译器(也许不是)都会警告您:
clang:
control may reach end of non-void function
gcc:
control reaches end of non-void function
MVSC:
not all control paths return a value
它确实 有效,因为您的朋友很幸运没有让这个程序爆炸、内爆或在您的卧室里制造黑洞。未定义行为就是这样:您无法判断您的程序将如何运行。
标准对此是这样说的:
Flowing off the end of a constructor, a destructor, or a function with a cv void return type is equivalent to a return with no operand. Otherwise, flowing off the end of a function other than main (3.6.1) results in undefined behavior.