【问题标题】:Segmentation fault in recursive function, storing result in a vector递归函数中的分段错误,将结果存储在向量中
【发布时间】:2017-09-10 04:13:38
【问题描述】:

我不断收到此段错误,但我不知道它是从哪里来的。 抱歉,我还是编码新手。

#include <iostream>
#include <vector>

using namespace std;

vector<int> map(vector<int> v, vector<int>::iterator i, vector<int> result)  { //set i = v.begin() in main
    if (i==v.end()) {
        return result;
    }   else    {
        result.push_back((*i)*(*i));
        i++;
        map(v,i,result);
    }
}

int main()  {
    vector<int> v;
    vector<int> result;

    for (int i=0;i<20;i++)  {
        v.push_back(i);
    }

    vector<int>::iterator it=v.begin();

    result=map(v,it,result);
}

显然,我需要添加更多单词,因为我的问题主要是代码。

【问题讨论】:

  • 哪条线路有问题?
  • 通过引用而不是值传递你的向量。

标签: c++ function recursion vector segmentation-fault


【解决方案1】:

您按值传递向量,因此更改不会在函数调用之间持续存在。

通过引用传递向量来实现这一点。

另外,else情况下也需要返回向量。

此外,也通过引用传递v,以便在您检查v.end() 时迭代器正常。否则,它会在每次函数调用时查看 v 的不同副本。

把所有东西放在一起,你会得到:

vector<int> map(vector<int>& v, vector<int>::iterator i, vector<int>& result)  { 
    if (i==v.end()) {
        return result;
    }   else    {
        result.push_back((*i)*(*i));
        i++;
        return map(v,i,result);
    }
}

【讨论】:

  • @xaxxon 更新了,你现在怎么看?哦,我看到你也发布了一个答案,稍后会检查它(如果我喜欢,你会看到我的支持)。
【解决方案2】:

有两个问题:

由于您通过值传递第一个参数 (std::vector),因此对 map 的每次调用都使用与原始向量不同的向量。因此,您传递的迭代器与传入的向量不兼容,您的程序将表现出未定义的行为。

要解决此问题,请通过引用而不是值传递std::vector。由于您也没有更改函数内的vector,因此请通过const 参考:

vector<int> map(const vector<int>& v, vector<int>::iterator i, vector<int> result)

现在迭代器正在迭代传入的实际向量,而不是向量的临时副本。

第二个问题是您没有从 map 函数返回值。不从应该返回值的函数返回值是未定义的行为。

要解决此问题,请删除 else 语句(以避免任何编译器警告)并从函数返回值:

vector<int> map(const vector<int>& v, vector<int>::iterator i, vector<int> result) 
{   
   if (i == v.end()) 
      return result;
   result.push_back((*i)*(*i));
   i++;
   return map(v, i, result);
}

【讨论】:

    【解决方案3】:

    问题几乎可以肯定是因为在许多情况下您没有从递归函数返回值:

    vector<int> map(vector<int> v, vector<int>::iterator i, vector<int> result)  { //set i = v.begin() in main
        if (i==v.end()) {
            return result;
        }   else    {
            result.push_back((*i)*(*i));
            i++;
            map(v,i,result);
           /** NO RETURN VALUE HERE **/
        }
    }
    

    相反,将最后一行设为:

    return map(v,i,result);
    

    理想情况下,您不会按值传递向量,但这不会导致您的程序崩溃,只是运行得更慢。

    【讨论】:

      【解决方案4】:

      崩溃的一个潜在原因是递归调用后面没有(或部分)返回语句。当调用者访问返回值时,结果是未定义的行为。

      即使忽略这一点,参数也是按值传递的。因此,对向量所做的任何更改对调用者都是不可见的。更重要的是,测试i == v.end() 也将具有未定义的行为(崩溃的另一个潜在原因),因为iv.end() 不是从同一容器获得的迭代器(i 是来自@987654325 中的向量的迭代器@ 和 v 是该向量的副本 - 它具有完全不同的迭代器集)。

      最后,std::map 是标准库中的模板类型。拥有一个名为 map() 的函数 - 特别是在使用 using namespace std 时,可能会使程序员感到困惑,如果不会导致编译器产生歧义的话。

      【讨论】:

        猜你喜欢
        • 2014-04-08
        • 2013-03-05
        • 2019-11-16
        • 1970-01-01
        • 2017-12-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多