smilingbuddha
smilingbuddha

Reputation: 14702

Addition of vectors c++. Cannot understand compilation error

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

Answers (2)

Sarfaraz Nawaz
Sarfaraz Nawaz

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.

Explanation:

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)

Getting familiar with operator+

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?

Getting familiar with Standard algorithm..

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

Steven Keith
Steven Keith

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

Related Questions