在 C++ 中通过引用传递数组
Pass array by reference in C++
我有一个 Fortran 代码,我需要在其中对两个相互关联的数组进行排序。我想在 C++ 函数中执行此操作,以便利用 STL 中的内置排序算法。因为 Fortran 是按引用传递的,所以 C++ 函数的所有参数都必须是指针。下面的函数 esort
对数组进行了正确排序,但没有 return 正确的值。我相信这是因为指针是按值传递的,所以函数末尾的更新没有效果。我应该如何更改我的代码才能达到预期的效果?
#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_lam
和 res_vec
有我希望他们在例程结束时拥有的价值观。我的问题是将这些值 returned 到调用程序。
void esort(double* lambda, double* vecs, int* n)
调用此函数时,它会创建引用相同内存地址的局部指针变量。在完成以下操作后的代码中:
lambda = res_lam;
vecs = res_vec;
这并不意味着您正在更改作为参数传递给函数的内存地址的值,而是函数的局部指针变量 lambda
和 vecs
现在是指向不同的内存地址。
或者,您可以使用指向指针概念的指针。
void esort(double** lambda, double** vecs, int* n)
确实,C++ 通过值传递其所有参数,包括指针,这意味着分配给 lambda
和 vecs
对调用者没有影响:这些变量仅 点到数据。您需要将结果复制到指向的内存中,如下所示,使用 <algorithm>
中的 copy
。另外 rbegin
和 rend
是反向迭代器,这会导致 sort
从您想要的内容向后排序;我将其更改为 begin
和 end
。我进一步建议使用 vector
作为临时 res_lam
和 res_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);
}
我有一个 Fortran 代码,我需要在其中对两个相互关联的数组进行排序。我想在 C++ 函数中执行此操作,以便利用 STL 中的内置排序算法。因为 Fortran 是按引用传递的,所以 C++ 函数的所有参数都必须是指针。下面的函数 esort
对数组进行了正确排序,但没有 return 正确的值。我相信这是因为指针是按值传递的,所以函数末尾的更新没有效果。我应该如何更改我的代码才能达到预期的效果?
#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_lam
和 res_vec
有我希望他们在例程结束时拥有的价值观。我的问题是将这些值 returned 到调用程序。
void esort(double* lambda, double* vecs, int* n)
调用此函数时,它会创建引用相同内存地址的局部指针变量。在完成以下操作后的代码中:
lambda = res_lam;
vecs = res_vec;
这并不意味着您正在更改作为参数传递给函数的内存地址的值,而是函数的局部指针变量 lambda
和 vecs
现在是指向不同的内存地址。
或者,您可以使用指向指针概念的指针。
void esort(double** lambda, double** vecs, int* n)
确实,C++ 通过值传递其所有参数,包括指针,这意味着分配给 lambda
和 vecs
对调用者没有影响:这些变量仅 点到数据。您需要将结果复制到指向的内存中,如下所示,使用 <algorithm>
中的 copy
。另外 rbegin
和 rend
是反向迭代器,这会导致 sort
从您想要的内容向后排序;我将其更改为 begin
和 end
。我进一步建议使用 vector
作为临时 res_lam
和 res_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);
}