Reputation: 14702
Hi I am have written the following function for adding 2 vectors
vector<double> add(vector<double>& v1, vector<double>& v2 )
{ /*Do quick size check on vectors before proceeding*/
vector<double> result(v1.size());
for (unsigned int i = 0; i < result.size(); ++i)
{
result[i]=v1[i]+v2[i];
}
return result;
}
Now I tried to add 3 vectors a,b,c all of same size in the following two ways
vector <double> sum1, sum2;
sum1=add(b,c);
sum2=add(a,sum1);
which worked
and
vector <double> sum;
sum=add(a,add(b,c));
which gave me the following compiler error
g++ -Wall simple.cpp
simple.cpp: In function ‘int main(int, char**)’:
simple.cpp:45: error: invalid initialization of non-const reference of type ‘std::vector<double, std::allocator<double> >&’ from a temporary of type ‘std::vector<double, std::allocator<double> >’
simple.cpp:16: error: in passing argument 2 of ‘std::vector<double, std::allocator<double> > add(std::vector<double, std::allocator<double> >&, std::vector<double, std::allocator<double> >&)’
Why did the second method not work?
Upvotes: 1
Views: 2683
Reputation: 361762
vector<double> add(vector<double> v1, vector<double> v2 )
From the error message, I can say with 100% certaintly that this is not the function signature in your original code.
In your original code, you must be using this:
vector<double> add(vector<double> & v1, vector<double> & v2 )
If so, then make it as:
vector<double> add(const vector<double> & v1, const vector<double> & v2)
Now it should work just fine.
The return value of add()
is a temporary object, and a temporary object cannot be bound to non-const reference. That is why the compiler was giving error. It will give same error if you write this:
vector<double> & v = add(a,b); //error
However, if a temporary object can be bound to const
reference. That is why I suggested you to make the parameter const
reference. That means, you can write this:
const vector<double> & v = add(a,b); //ok
Also, you can make the parameter non-const non-reference as well, that is, pass the arguments by value. But I would not recommend that, as it involves unnecessary copies of the vectors.
The best solution is this:
vector<double> add(const vector<double> & v1, const vector<double> & v2)
You could also overload operator+
for vector, as:
vector<double> operator + (const vector<double>& v1, const vector<double>& v2 )
{
/*Do quick size check on vectors before proceeding*/
vector<double> result(v1.size());
for (unsigned int i = 0; i < result.size(); ++i)
{
result[i]=v1[i]+v2[i];
}
return result;
}
If you overload this, then you can write this cool code:
vector<double> c = a + b;
vector<double> d = a + b + c;
vector<double> e = a + b + c + d;
//so on
Isn't it fun?
As @Gene commented, you could use std::transform
in the function as:
vector<double> operator+(const vector<double>& v1, const vector<double>& v2 )
{
vector<double> result;
std::transform(v1.begin(),v1.end(),v2.begin(),
std::back_inserter(result), std::plus<double>);
return result;
}
Upvotes: 7
Reputation: 1799
vector<double> add(vector<double>& v1, vector<double>& v2 )
Because we expect the function to modify its arguments, we cannot call the function with just any expression. Instead we must pass an lvalue argument to a reference parameter. An lvalue is a value that denotes a nontemporary object.
sum=add(a,add(b,c));
The preceding call to add tries to pass a temporary object.
Upvotes: 0