C++ - 无法从函数返回向量

Posted

技术标签:

【中文标题】C++ - 无法从函数返回向量【英文标题】:C++ - Cannot return vector from function 【发布时间】:2016-06-24 08:33:06 【问题描述】:

假设以下函数

std::vector<double> LocatePulseEdges(int points, double* signal_x, double* signal_y, double threshold, vector<double> left_edge, vector<double> right_edge)
cout << "1" << endl;
    for (int i=0; i<points; i++)
        if(signal_y[i]<threshold)// left side of the pulse
            left_edge.push_back(signal_x[i]);
            break;
        
        if(signal_y[i]>threshold)// right side of the pulse
            right_edge.push_back(signal_x[i]);
            break;
        
    
cout << "6" << endl;
    return left_edge;
    //return right_edge;

cout << "7" << endl;

我在下面的代码中调用了这个函数

void Analyze()
    int points = 90000000;//hSignal->GetNbinsX();
    double* x          = new double[points];           // SIZE limited only by OS/Hardware
    double* y          = new double[points];
    std::vector<double> left;
    std::vector<double> right;
    double threshold = 6234.34;

    Function_to_Fill_X_and_Y();
    LocatePulseEdges(points, x, y, threshold, left, right);
    cout << "First left threshold crossing @ time : " << left[0] << endl;

虽然我没有收到编译错误,但当我运行程序时,它会在返回语句之前崩溃。

知道为什么会这样吗?

【问题讨论】:

@Boiethios :嗯......我该如何检查?如果是这种情况,我该如何解决? 对不起,我猜不是这样。 @Thanos 为什么要按值传递向量? @GMichael :我还能做什么?我对指针不太熟悉...... :( @Thanos 阅读参考资料... 【参考方案1】:

LocatePulseEdges 函数和Analyze 函数存在几个缺陷。

首先,如果您要在代码的一部分中使用std::vector&lt;double&gt;,为什么不始终使用它呢?你有:

void Analyze()

  //...        
  double* x = new double[points]; 
  double* y = new double[points];
 //...

除非您调用了delete [] xdelete [] y,否则此函数存在内存泄漏。你可以简单地使用

std::vector&lt;double&gt; x(points), y(points);

在填充它们的函数中,如果使用 C++11,则传递 x.data()y.data(),否则传递 &amp;x[0]&amp;y[0]。这缓解了内存泄漏。

即使你在某处确实有delete [],如果抛出异常,delete [] 可能会被绕过,从而导致泄漏。使用std::vector,即使出现异常,vector 也会被销毁。


其次,对于LocatePulseEdges 函数,传递向量的(常量)引用,而不是值。此外,不需要按值返回向量。如果您在函数中创建一个全新的向量,那么这可能会证明返回新向量是合理的,但您没有这样做。所以返回一个void

void LocatePulseEdges(int points, double* signal_x, double* signal_y, double threshold, vector<double>& left_edge, vector<double>& right_edge)

    //...

当您按值传递向量时,会生成向量的副本,因此您的 left_edge.push_back() 调用是在使用临时的,而不是使用您传递的实际向量。这就是为什么返回时,向量 left_edge 是空的。


最后,如果您要访问向量中的第一项,请检查vector::empty()。您不能只假设该项目存在于向量中。

   LocatePulseEdges(points, x.data(), y.data(), threshold, left, right);
   if ( !left.empty() ) 
       cout << "First left threshold crossing @ time : " << left[0] << endl;
   else
       cout << "No threshold's generated" << endl; 

上面的代码假设您接受了将std::vector&lt;double&gt; 用于xy 变量的建议。

【讨论】:

【参考方案2】:

通过引用传递您的 left_edge,以便您的功能可以修改它:

void LocatePulseEdges((int points, double* signal_x, double* signal_y, double threshold, 
std::vector<double> &left_edge, std::vector<double> &right_edge)

    //do your stuff

当你给出没有&amp; 的参数时,程序会复制你的参数的值然后使用它。所以你不能修改它。使用&amp; 传递参数称为按引用传递。

当你通过引用传递一个对象时,你可以修改它,而且速度更快。如果你需要传递一个对象而不修改它,给一个 const ref :

void foo(const std::vector<double> &vec)

void foo(std::vector<double> vec)

并防止您修改 vec,这要归功于 const 关键字。

补充说明:

void 函数不需要任何返回,但在许多情况下最好使用 Bool 函数

Bool LocatePulseEdges()

    //do your stuff
    return True ;

这样做可以让您在出现任何问题时提前返回 False。

【讨论】:

【参考方案3】:

基于 cmets 我得到了:

    更改 LocatePulseEdges 函数以使用参考:

    void LocatePulseEdges((int points, double* signal_x, double* signal_y, double threshold, std::vector<double> &left_edge, std::vector<double> &right_edge) //do your stuff 所以你可以改变函数内部参数的值

    在访问之前检查元素是否存在于向量中:

    if (left.size() <= index) return left[index];

    现在你的代码出了什么问题。 for (int i=0; i&lt;points; i++) 被执行,因为points = 9000000,但signal_y[i]&lt;threshold 永远不会为真(它没有在你的代码中的任何地方初始化),所以没有任何东西被插入到left

【讨论】:

以上是关于C++ - 无法从函数返回向量的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 中的函数返回向量或数组

如何从 C++ 中的函数返回向量?

C++ 从函数调用的多次返回中构建字符串向量的最佳方法

从函数C++返回3个元素[重复]

如何在 C++ 中返回从零开始的向量索引

C++ 函数返回一个向量/字符串,但不是一个数组