I have a Fortran code in which I need to sort two arrays that are related to each other. I would like to do this in a C++ function in order to leverage the built-in sort algorithm in the STL. Because Fortran is pass-by-reference, all arguments to the C++ function must be pointers. The following function esort
sorts the arrays correctly, but does not return the correct values. I believe this is because the pointers are passed by value, so the update at the end of the function has no effect. How should I change my code to achieve the desired effect?
#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;
}
Output:
lambda
0.5 2 1
vecs
0.5 2 1
0.5 2 1
0.5 2 1
Desired Output:
lambda
0.5 1 2
vecs
0.5 1 2
0.5 1 2
0.5 1 2
EDIT: The ith element of lambda
corresponds to the ith column of vecs
(in Fortran's column-major order). In order to avoid hassling with multi-dimensional arrays in C++, I am simply representing vecs
as a 1D array within esort
. The point of esort
is to sort lambda
and then reorder vecs
such that the ith element of lambda
still corresponds to the ith column of vecs
.
EDIT 2: By placing cout
statements inside esort
, I have confirmed that res_lam
and res_vec
have the values that I want them to have at the end of the routine. My issue is getting those values returned to the calling program.
It is true that C++ passes all of its arguments by value, including pointers, meaning that assigning to lambda
and vecs
has no effect on the caller: those variables only point to the data. You need to copy your results into that pointed-to memory, as shown below by using copy
from <algorithm>
. Also rbegin
and rend
are reverse iterators, which causes sort
to sort backward from what you wanted; I changed it to begin
and end
. I would further suggest using vector
for your temporary res_lam
and res_vec
arrays.
#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);
}
void esort(double* lambda, double* vecs, int* n)
When calling this function, it creates local pointer variables that reference the same memory address. In the code when the following is done:
lambda = res_lam;
vecs = res_vec;
It doesn't mean that you are changing the value of the memory address you passed as argument to the function, but rather the local pointer variable of the function lambda
and vecs
are now pointing to a different memory address.
或者,您可以使用“指针到指针”概念。
void esort(double** lambda, double** vecs, int* n)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.