Недопустимая инициализация неконстантной ссылки типа

В следующем коде я не могу передать временный объект в качестве аргумента функции printAge:

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;
}

Ошибка, которую я получаю:

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

Я понимаю, что это связано с передачей lValue функции, ожидающей rValue... Есть ли способ конвертировать мой lValue в rValue с помощью std:: move или что-то еще? Я попытался использовать постоянный параметр, но это не работает.

Ответы

Ответ 1

Просто сделайте, чтобы ваша функция печати приняла ваш аргумент const&. Это также логически правильно, поскольку оно не изменяет ваш аргумент.

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

Реальная проблема - это наоборот. Вы передаете временную (rvalue) функцию, которая ожидает lvalue.

Ответ 2

Или, если у вас есть компилятор, совместимый с С++ 11, можно использовать так называемый универсальный ссылочный подход, который посредством правил сворачивания ссылок может связываться с ссылками lvalue и rvalue:

#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;
}

Или, в С++ 14,

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

Ответ 3

Ваш код не работает, если вы запускаете g++ или gcc-компиляторы. Вам нужно добавить const в void printAge(const Person &person). Однако в Visual Studio он будет работать нормально. Я тестировал VS2010 и VS2012, и в обоих случаях код работает нормально.

 #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;
}