2014-11-27 10 views
15

Im folgenden Code, ich bin nicht in der Lage ein temporäres Objekt als Argument an die printAge Funktion zu übergeben:Ungültige Initialisierung der nicht konstante Referenz vom Typ

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

Der Fehler, den ich bekommen ist:

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

Ich weiß, dass dies etwas damit zu tun hat, einen lValue an eine Funktion zu übergeben, die einen rValue erwartet ... Gibt es eine Möglichkeit, meinen lValue mit std :: move oder etwas in rValue umzuwandeln? Ich habe versucht, einen konstanten Parameter zu nehmen, aber das scheint nicht zu funktionieren.

+0

Es ist umgekehrt. Sie übergeben einen Rvalue an eine Funktion, die einen Lvalue erwartet. Nicht-konstante lvalue-Referenzen können nicht an rvalues ​​binden, aber Sie können stattdessen eine 'const' lvalue-Referenz verwenden. – juanchopanza

+4

"Ich habe versucht, einen konstanten Parameter zu nehmen, aber das scheint zu funktionieren." Sie haben das Problem also gelöst, aber entschieden, die Lösung zu verwerfen, weil sie zu funktionieren scheint? – molbdnilo

+0

Hoppla, ich habe ein * nicht * gelassen! – jeffreyveon

Antwort

14

Nehmen Sie einfach Ihre Druckfunktion nehmen Sie Ihr Argument von const&. Dies ist auch logisch richtig, da es Ihr Argument nicht ändert.

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

Das eigentliche Problem ist anders herum. Sie übergeben einen temporären (rvalue) an eine Funktion, die einen lvalue erwartet.

-2

Ihr Code funktioniert nicht, wenn Sie g ++ oder gcc Compiler ausführen. Sie müssen const zu void printAge(const Person &person) hinzufügen. In Visual Studio wird es jedoch einwandfrei funktionieren. Ich habe für VS2010 und VS2012 getestet und in beiden funktioniert der folgende Code gut.

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

Nein, das sollte nicht kompiliert werden. Dies muss wieder eine MSVC-Erweiterung sein. – inf

+0

Ja, ich habe gerade g ++ oder gcc eingecheckt; Beide kompilieren es nicht; aber in VS ist es sehr normal, ein Objekt als Argument zu übergeben, obwohl es nicht const definiert ist; es sollte jedoch vermieden werden. – telcom

+1

Sie können es vermeiden, aber für einen VS-Benutzer ist es in Ordnung, es zu verwenden. – telcom

10

Oder, wenn Sie einen C++ 11-kompatible Compiler haben, können verwendet werden, die so universell Referenz Ansatz genannt, die über Referenz kollabiert Regeln für beide L-Wert und rvalue Referenzen binden können:

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

Oder in C++ 14,

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

Dies ist nicht, was Urefs sind. Wenn Sie eine schreibgeschützte Ansicht einer Variablen wünschen, sollten Sie sie einfach mit 'const &' übernehmen. – inf

+0

@bamboon können Sie auf diese erweitern? habe deinen Kommentar nicht wirklich verstanden. sagst du, dass urefs nur für die perfekte Weiterleitung sind? Harnstoffe funktionieren hier jedoch einwandfrei. Ok, habe deinen Kommentar gesehen, stimme zu. – vsoftco

+0

Ja, im Grunde. Obwohl ich nicht denke, dass es wirklich falsch ist, denke ich, dass es das Problem und den Grund dafür, dass niemand mehr weiß, wie man Variablen richtig weitergibt, furchtbar überkompensiert (z. B .: siehe Herb Sutters Vortrag bei cppcon). Edit: Ah ja, ich drücke das erste Mal irgendwie zu schnell dort rein. – inf

Verwandte Themen