为什么每次递归后我的变量都没有增加?

时间:2019-06-04 00:44:51

标签: c++ recursion

所以我对C ++还是很陌生,我正尝试使用递归来生成斐波那契数,对吗?除了当我尝试索引下一个值时,我需要增加索引,而该函数不会让我增加它。

我知道的是,我已在调试模式下运行它并跨过函数-它在fibGen函数内部连续循环,而我保持恒定值1(当我在主函数中调用fibGen时,参数是(startingSeq,1,13),其中startingSeq是另一个值为{1,1}的向量

代码可以很好地构建和编译,但是当我运行它时,我得到了一个内存分配错误,这是由似乎有无限循环的原因引起的。

我做错了什么?为什么“ i”没有增加?

我已经尝试通过在递归的fibGen调用中(在else语句中)使用i ++来增加i,我已经尝试在函数调用之外使用i ++,并且现在尝试了其中存在i +的内容= 1,然后让我通过。

我本来也没有底部的“ return fibSeq”,因为在那里没有意义,但是我把它放进去是因为如果没有它,vscode不会编译,说永远不会到达fibGen的末尾(这很有意义,而且当此问题解决后,我认为可以将其消除,但是目前它就在那里,以便程序可以编译)

std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){

    if(fibSeq[i] >= max){
        return fibSeq;
    }else{
        fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
        i+=1;
        fibGen(fibSeq, i, max);
    } 

    return fibSeq;  
}

输出应该是包含斐波那契序列的向量,并且我遇到了内存分配错误(如上所述)

2 个答案:

答案 0 :(得分:3)

实际上,您的代码有效。您只是次优地处理结果向量。与您的声明:

std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max)

您将始终传递矢量的副本(并且您永远不会使用返回的值)。相反,您可能想要做的是处理相同的数据。为此,请使用对向量的引用(用&表示)。然后,您无需返回任何内容:

void fibGen(std::vector<int>& fibSeq, int i, int max) {

    if (fibSeq[i] >= max) {
        return;
    }
    else {
        fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
        i += 1;
        fibGen(fibSeq, i, max);
    }
}

void main(void) {
    std::vector<int> fib = { 1, 1 };
    fibGen(fib, 1, 34);
    for (auto i : fib)
        std::cout << i << std::endl;
}

答案 1 :(得分:0)

因此,直到我意识到在您的实际代码中,您是在执行此操作而不是在发布的代码中进行操作,我才能重现该错误:

std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){

    if(fibSeq[i] >= max){
        return fibSeq;
    }else{
        fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
        i+=1;
        fibGen(fibSeq, i, max);
    } 
}

至少在Visual Studio 2010中,它可以正常编译,但是在运行时引发了一个错误,我相信这就是您所描述的。所以我假设我已经复制了它。

引发错误的原因是因为you are invoking C++'s infamous undefined behavior。 C ++ permits anything to happen中的未定义行为,如未编译失败,但引发运行时错误。

修复很简单。您只需要在所有执行路径中返回一个值。或者,简而言之,只需执行以下操作:

std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){

    if(fibSeq[i] >= max){
        return fibSeq;
    }else{
        fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
        i+=1;
        return fibGen(fibSeq, i, max); 
        // Notice we are returning the value of the recursive call to fibGen().
        // We can do this because we have already modified the vector the way we need to,
        // so just simply returning the value is fine
    } 
}

当然,您也可以改用Nico Schertler's suggestion

void fibGen(std::vector<int>& fibSeq, int i, int max) {

   if (fibSeq[i] >= max) {
       return;
   }
   else {
       fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
       i += 1;
       fibGen(fibSeq, i, max);
   }
}

应该注意,不从void函数返回值并不是未定义的行为(据我所知),但实际上是void的工作原理,因此该函数可以不返回值就可以了。