【问题标题】:Pass array by reference in C++在 C++ 中通过引用传递数组
【发布时间】:2015-06-24 03:30:12
【问题描述】:

我有一个 Fortran 代码,我需要在其中对两个相互关联的数组进行排序。我想在 C++ 函数中执行此操作,以便利用 STL 中的内置排序算法。因为 Fortran 是按引用传递的,所以 C++ 函数的所有参数都必须是指针。以下函数esort 对数组进行正确排序,但不返回正确的值。我相信这是因为指针是按值传递的,所以函数末尾的更新没有效果。我应该如何更改我的代码以达到预期的效果?

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

void esort(double* lambda, double* vecs, int* n) {

  double* res_lam = new double[*n];
  double* res_vec = new double[*n * *n];
  vector<pair<double, int> > order(*n);

  for (int i=0; i<*n; i++) {
    order[i] = make_pair(lambda[i], i);
  }

  sort(order.rbegin(), order.rend());

  for (int i=0; i<*n; i++) {
    pair<double, int> p = order.at(i);
    res_lam[i] = p.first;
    for (int j=0; j<*n; j++) {
      res_vec[*n*i + j] = vecs[*n*p.second + j];
    }
  }

  lambda = res_lam;
  vecs = res_vec;

  delete [] res_lam;
  delete [] res_vec;

  return;
}

int main() {

  double lambda[] = {0.5, 2.0, 1.0};
  double vecs[] = {0.5, 0.5, 0.5, 2.0, 2.0, 2.0, 1.0, 1.0, 1.0};
  int n = 3;

  esort(lambda, vecs, &n);

  cout << "lambda" << endl;
  for (int i=0; i<n; i++) {
    cout << lambda[i] << " ";
  }
  cout << endl;
  cout << "vecs" << endl;
  for (int i=0; i<n; i++) {
    for (int j=0; j<n; j++) {
      cout << vecs[j*n + i] << " ";
    }
    cout << endl;
  }

  return 0;
}

输出:

lambda
0.5 2 1 
vecs
0.5 2 1 
0.5 2 1 
0.5 2 1

期望的输出:

lambda
0.5 1 2 
vecs
0.5 1 2 
0.5 1 2 
0.5 1 2

编辑:lambda 的第 i 个元素对应于vecs 的第 i 列(按 Fortran 的列优先顺序)。为了避免在 C++ 中使用多维数组,我只是将vecs 表示为esort 中的一维数组。 esort的重点是对lambda进行排序,然后对vecs重新排序,使得lambda的第i个元素仍然对应vecs的第i列。

编辑 2: 通过在 esort 中放置 cout 语句,我已经确认 res_lamres_vec 具有我希望它们在例程结束时具有的值.我的问题是将这些值返回给调用程序。

【问题讨论】:

  • “因为Fortran是按引用传递的,所以C++函数的所有参数都必须是指针”等等
  • 嗯,你似乎对指针感到困惑。如果你真的想利用 C++ 的特性,这真的是最糟糕的方式。
  • @LightnessRacesinOrbit,我对 C++ 还很陌生,所以我绝对愿意接受有关更好的做事方式的建议。
  • 您说数组是相互关联的,但是除了通过代码(您自己承认)不能准确地表示这种关系之外,您没有告诉我们那是怎么回事。请用文字说明您的要求/目标。
  • 您是尝试通过引用传递数组,还是通过引用传递指针?因为标题问的是前者,而代码建议的是后者。

标签: c++ arrays function argument-passing


【解决方案1】:

C++ 确实通过值传递其所有参数,包括指针,这意味着分配给lambdavecs 对调用者没有影响:这些变量仅指向数据。您需要将结果复制到指向的内存中,如下所示,使用来自&lt;algorithm&gt;copyrbeginrend 也是反向迭代器,这会导致 sort 从您想要的内容向后排序;我将其更改为beginend。我会进一步建议将vector 用于您的临时res_lamres_vec 数组。

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;

void esort(double* lambda, double* vecs, int* n) {

  vector<double> res_lam(*n);
  vector<double> res_vec(*n * *n);
  vector<pair<double, int> > order(*n);

  for (int i=0; i<*n; i++) {
    order[i] = make_pair(lambda[i], i);
  }

  sort(order.begin(), order.end());

  for (int i=0; i<*n; i++) {
    pair<double, int> p = order.at(i);
    res_lam[i] = p.first;
    for (int j=0; j<*n; j++) {
      res_vec[*n*i + j] = vecs[*n*p.second + j];
    }
  }

  copy(res_lam.begin(), res_lam.end(), lambda);
  copy(res_vec.begin(), res_vec.end(), vecs);
}

【讨论】:

  • 谢谢,这正是我想要的。
【解决方案2】:

void esort(double* lambda, double* vecs, int* n)

调用此函数时,它会创建引用相同内存地址的局部指针变量。在完成以下操作后的代码中:

lambda = res_lam;
vecs = res_vec;

这并不意味着您正在更改作为参数传递给函数的内存地址的值,而是函数 lambdavecs 的局部指针变量现在指向不同的内存地址.

【讨论】:

  • 技术上正确。然而,在这里重新分配内存是一件非常愚蠢的事情。所以这不是一个好的解决方案。
  • @Ediac,那么我该如何修复我的代码?我尝试了void esort(double* &amp;lambda, double* &amp;vecs, int* n),但每当我尝试访问lambdavecs 的元素时,都会出现段错误。
  • 是的,我知道,只是强调了 OP 的错误 :)
  • @LightnessRacesinOrbit,您能否详细说明我如何在不重新分配内存的情况下仍能实现目标?
  • @astay13 走了一会,现在好像又有新答案了
【解决方案3】:

您也可以使用指针到指针的概念。

void esort(double** lambda, double** vecs, int* n)

【讨论】:

    猜你喜欢
    • 2013-11-07
    • 2010-11-09
    • 1970-01-01
    • 2020-07-30
    • 2012-04-17
    • 2019-06-29
    • 2015-07-08
    相关资源
    最近更新 更多