jeffreyveon
jeffreyveon

Reputation: 13820

Invalid initialization of non-const reference of type

In the following code, I'm not able to pass a temporary object as argument to the printAge function:

struct Person {
  int age;
  Person(int _age): age(_age) {}
};

void printAge(Person &person) {
   cout << "Age: " << person.age << endl;
}

int main () {
  Person p(50);
  printAge(Person(50));  // fails!
  printAge(p);
  return 0;
}

The error I get is:

error: invalid initialization of non-const reference of type ‘Person&’ from an rvalue of type ‘Person’

I realize that this is something to do with passing an lValue to a function expecting a rValue... Is there a way to convert my lValue to rValue by using std::move or something? I tried taking a constant parameter, but that does not seem to work.

Upvotes: 18

Views: 37715

Answers (3)

vsoftco
vsoftco

Reputation: 56547

Or, if you have a C++11-compliant compiler, can use the so called universal reference approach, which, via reference collapsing rules, can bind to both lvalue and rvalue references:

#include <iostream>
using namespace std;

struct Person {
  int age;
  Person(int _age): age(_age) {}
};

template<typename T> // can bind to both lvalue AND rvalue references
void printAge(T&& person) {
   cout << "Age: " << person.age << endl;
}

int main () {
  Person p(50);
  printAge(Person(50));  // works now
  printAge(p);
  return 0;
}

Or, in C++14,

void printAge(auto&& person) {
   cout << "Age: " << person.age << endl;
}

Upvotes: 10

JavadT
JavadT

Reputation: 153

Your code doesn't work if you run g++ or gcc compilers. You need to add const to void printAge(const Person &person). However, in Visual Studio it will work fine. I've tested for VS2010 and VS2012 and in both the following code works fine.

 #include<iostream>

using namespace std;
struct Person {
  int age;
  Person(int _age): age(_age) {}
};

void printAge(Person &person) {
   cout << "Age: " << person.age << endl;
}

int main () {
  Person p(50);
  printAge(Person(50));  // DOES NOT fail!
  printAge(p);
  return 0;
}

Upvotes: -2

Stephan Dollberg
Stephan Dollberg

Reputation: 34528

Simply make your print function take your argument by const&. This is also logically right as it doesn't modify your argument.

void printAge(const Person &person) {
   cout << "Age: " << person.age << endl;
}

The actual problem is the other way around. You are passing a temporary(rvalue) to a function which expects an lvalue.

Upvotes: 18

Related Questions