【问题标题】:C++ Aborted (Core Dumped) when returning a vector from a function从函数返回向量时 C++ 中止(核心转储)
【发布时间】:2017-04-03 07:02:43
【问题描述】:

我正在尝试从函数返回一个向量。我的代码编译并且我检查了我的函数并认为错误来自返回部分。它编译得很好(使用 Cygwin),但是在运行它时,我得到一个 Aborted (core dumped) 错误。 这是我的代码:

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

//function that returns the square
int f(int n)
{
    return n*n;
}
vector<int> myVec;
int counter = 0;
//function that uses f on all elements in a list
vector<int> map(vector<int> something)
{
    //base case
    if(counter == something.size())
    {
        /*cout << "hello" << endl;
        for (int i=0; i<counter; i++)
        {
            cout << "vector: " << myVec[i] << endl;
        }*/
        counter=0;
        return myVec;
    }
    //recursion
    else
    {
        //cout << "counter: " << counter << endl;
        int n = f(something[counter]);
        //cout << "n: " << n << endl;
        myVec.push_back(n);
        //cout << "vector: " << myVec[counter] << endl;
        counter++;
        map(something);
    }
}

int main()
{
    //making vectors
    vector<int> L;
    vector<int> L1;
    vector<int> L2;
    for (int i=0; i<20; i++)
    {
        L.push_back(i);
    }
    L1 = map(L);
}

代码最初来自一个类文件。

【问题讨论】:

  • 编译代码时打开警告,然后它会告诉您“并非所有路径都返回值”。由于返回的对象的析构函数由编译器调用,并且当您“不返回任何内容”时会返回垃圾,因此使用垃圾作为输入调用析构函数 - 这很可能会崩溃,因为有效的向量将包含指针等。
  • 我在编译时使用了-Wall,只是收到关于比较有符号和无符号整数的警告以及关于控制到达非空函数结束的警告。
  • 不相关,但在递归调用中使用全局参数不是一个好的设计,除非您证明您的函数不是线程安全的,并且将其封装在另一个初始化全局变量的函数中。
  • 是的,因为 counter 最初在我的构造函数中。
  • 那么你使用的是非常旧版本的 gcc 吗? clang 和 gcc 都给了我一个警告 - clang 甚至没有要求 -Wall。

标签: c++ vector return


【解决方案1】:

在您的递归中,您不返回任何内容。该函数应返回一个向量。

在您的情况下,如果函数在第一次调用时进入“else”情况会发生什么?它重新进入 map() 直到满足条件,然后返回一个向量。该向量被传递到上一个递归调用并立即删除,因为它不再被传递。

这里的解决方案是将 else-case 的最后一行更改为

return map(something);

因此该值不会丢失并正确传递给原始调用者(您的主函数)。

【讨论】:

  • 非常感谢!我完全忘记了返回函数!
【解决方案2】:

当您的返回类型是向量时,总是返回一个向量。在您的函数中,有一个不会返回任何内容的分支,这会导致问题。

vector<int> map(vector<int>& something)
{
    //base case
    if(counter == something.size())
    {
        /*cout << "hello" << endl;
        for (int i=0; i<counter; i++)
        {
            cout << "vector: " << myVec[i] << endl;
        }*/
        counter=0;
        return myVec;
    }
    //recursion
    else
    {
        //cout << "counter: " << counter << endl;
        int n = f(something[counter]);
        //cout << "n: " << n << endl;
        myVec.push_back(n);
        //cout << "vector: " << myVec[counter] << endl;
        counter++;
        map(something); //you should return a vector here
        return std::vector<int>(); //empty vector
    }
}

还要注意我在函数调用中添加的“&”符号,以便通过引用传递向量。否则,您将传递一个不会更改的副本。我不知道那个“地图”功能是做什么的,所以我不能为你正在做的事情推荐更好的模型。

【讨论】:

  • 啊,我明白了,有没有办法绕过在我的 else 语句中返回一些东西?我不想在我的 else 语句中返回任何内容。我的 map 函数使用 f 函数返回一个向量,它的所有元素都受 f 函数的影响。它使用递归来做到这一点。
  • 好吧,你可以保持原样,然后检查向量是否为空。或者,您可以通过引用传递另一个应该具有结果的向量,并根据需要对其进行修改。有很多很多方法。但请记住,C++ 是非常低级的。您直接处理内存和处理器。如果一个函数期望返回一个向量,它必须返回一个向量。我认为你的编译器警告过你。否则你会有未定义的行为
  • 我明白了,但如果你必须在递归情况下返回一些东西,它有点违背了使用递归的目的。
  • @Hypofreak 同样,你有很多方法可以做到这一点。这都是设计的问题。在我的脑海中,您可以创建一个结构/类,其中包含一个向量和一个标志是否有结果。顺便说一句,它并没有破坏目的。您可能已经习惯了像 Python 这样的脚本语言,其中一切都是同一个对象。在低级编程语言中,你必须有不同的想法。
  • @Hypofreak:“这有点违背了使用递归的目的” ...不。 Zinki 的回答是调用递归并立即返回其结果。
猜你喜欢
  • 2021-02-18
  • 2013-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多