为什么通过引用传递修复了我的递归错误?

Ian*_*004 1 c++ recursion vector

我刚刚开始学习递归,并且我有一个程序可以搜索5个int的向量作为值,并返回值的下标位置.我注意到,当我按值传递向量时,我得到一个不正确的下标位置,如72784658.

但是,当我通过引用传递向量时,不做其他更改,我得到了正确的答案.有人可以解释原因吗?下面是按值传递向量的代码,它产生错误的答案.

#include <vector>
#include <iostream>
using namespace std;

int search( vector<int>, int, int );

int main() 
{
    vector<int> myInts;
    for( int i = 0; i < 5; i++ )
        myInts.push_back( i );

    cout << "The number 2 is at subsript " << search( myInts, 2, 0 ) << endl;

    return 0; 
}

int search( vector<int> vec, int val, int index )
{
    if( index < vec.size() )
    {
        if( vec[index] == val )
            return index;
        else
            search( vec, val, index + 1 );
    }
    else
        return -1;
}
Run Code Online (Sandbox Code Playgroud)

cdh*_*wie 5

你递归,但不返回递归调用的值:

search( vec, val, index + 1 );
// Should be this:
return search( vec, val, index + 1 );
Run Code Online (Sandbox Code Playgroud)

这导致在不返回任何特定值的情况下到达函数的结尾,因此任何结果都是可能的,包括没有结果.在没有遇到return语句的情况下到达非void函数结束的流是未定义的行为,因此编译器在此时使程序崩溃是合法的.

更改vec为引用可能会导致index参数占用不同的CPU寄存器,可能是用于将值返回给调用者的CPU寄存器.这可以解释为什么当您更改vec为引用时它似乎工作,但升级编译器,更改编译器选项或使用不同的编译器可能会产生完全不同的结果.因此,即使它按照您想要的方式工作,也只是一个幸运的巧合.

作为旁注,始终编译时启用所有可能的警告,我还建议将所有警告错误(-Wall -pedantic).使用这些选项,此代码甚至无法编译.