I have a main function which looks like:
#include <iostream>
#include <vector>
#include <Eigen/Dense>
using Eigen::Vector3d;
using namespace std;
void ext_func(vector<Vector3d> &a, vector<Vector3d> &b, vector<Vector3d> &c);
int main()
{
vector<Vector3d> a = {};
a.push_back(Vector3d(1.,1.,0.));
a.push_back(Vector3d(2.,1.,0.));
vector<Vector3d> b = {};
b.push_back(Vector3d(.5,.7,2.));
b.push_back(Vector3d(0.,.2,-1.2));
vector<Vector3d> c = {};
c.push_back(Vector3d::Zero());
c.push_back(Vector3d::Zero());
ext_func(a,b,c);
}
From main
, I call an external function:
void ext_func(vector<Vector3d> &a, vector<Vector3d> &b, vector<Vector3d> &c)
{
double fac = 0.01;
for (size_t i = 0; i < a.size(); i++) {
auto a_temp = a[i] + fac * b[i] / 50.;
cout << "Before" << endl << fac*a_temp << endl;
a[i] = a_temp;
c[i] += fac*a_temp;
cout << "After" << endl << fac*a_temp << endl << endl;
}
}
The output is:
Before
0.010001
0.0100014
4e-06
After
0.010002
0.0100028
8e-06
Before
0.02
0.0100004
-2.4e-06
After
0.02
0.0100008
-4.8e-06
Which is not what I want to get (I want a_temp to stay constant once it's assigned). I understand that the problem is that I assign a new value to &a
and so when I'm calling a_temp
I'm basically incrementing a second time my initial a[i]
. The problem is solved by replacing auto
with Vector3d
or Vector3d&&
.
What I'm not sure about is what is auto
really doing here.
When calculating with matrices in the eigen library, the overloaded operators return an object representing the calculation expression. This expression is not yet evaluated (ie. the actual calculation is not yet performed).
In your example, the type derived by auto
is Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<double>, const Eigen::Matrix<double, 3, 1>, const Eigen::CwiseUnaryOp<Eigen::internal::scalar_quotient1_op<double>, const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, const Eigen::Matrix<double, 3, 1>>>>
.
The actual evaluation of the expression is done when the result is needed (eg. when assigning to a variable, printing, etc.).
Since a_temp
in your case is the expression (not the result), the expression is evaluated multiple times :
Before
linea[i]
c[i]
After
lineThe second of these ends up modifying one of the operands of the expression, so subsequent evaluations of the expression will have a different result.