为什么这种递归在C ++中起作用?

时间:2016-11-10 22:00:10

标签: c++ recursion return 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 ++的。

为什么我朋友的计划有效?它完全有效,还是未定义的行为?

4 个答案:

答案 0 :(得分:6)

为什么会这样?答:它没有。

else
{
    recursive(num + 1);
}

您朋友的节目缺少return声明。

else
{
    return recursive(num + 1);
}

不从非void函数返回值会导致未定义的行为。

在这种情况下,碰巧在您测试的计算机上,递归调用的返回值自动被&#34;返回&#34;对来电者 - 也许是因为它碰巧在正确的登记册中。这是纯粹的偶然事件。你不能依赖它。在不同的机器上,或者不同的编译器,甚至是不同的调用,程序也可以返回别的东西,或者崩溃,或做任何你能想象到的事情。

答案 1 :(得分:3)

在没有return语句的情况下结束函数是C ++中未定义的行为。我能做的最好的事情是推测关于发生了什么,我最好的猜测是调用recursive(index + 1),这是函数返回之前堆栈中的最后一件事,被拿起作为回报值。所以在(非标准的,非便携式的,一般用途的建议很差)意义上,代码隐式插入了return语句。

答案 2 :(得分:2)

这是未定义的行为。由于函数声明为返回布尔值,因此它将始终返回一些内容,但不一定是正确的值。

如果使用-Wall标记进行编译,GCC之类的编译器会向您发出此类代码的警告。

答案 3 :(得分:2)

当然,它有效!好吧,不是真的。

地球上的每个编译器(可能不会)会警告您:

  

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

工作,因为你的朋友很幸运,不会让你的程序爆炸,内爆或在你的卧室里造成黑洞。未定义的行为就是这样:您无法告诉您的程序将如何表现。

这就是标准所说的:

  

在构造函数,析构函数或具有cv void返回类型的函数的末尾流动,相当于没有操作数的返回。否则,流出函数的末尾而不是main(3.6.1)   导致未定义的行为