2010-06-06 9 views
5

ich folgenden Code versucht, nimmt:Pass temporäre Objekt-Funktion, die Zeiger

#include<iostream> 
#include<string> 
using namespace std; 

string f1(string s) 
{ 
    return s="f1 called"; 
} 

void f2(string *s) 
{ 
    cout<<*s<<endl; 
} 

int main() 
{ 
    string str; 
    f2(&f1(str)); 
} 

Aber dieser Code nicht kompiliert.
Was ich denke ist: f1 gibt nach Wert zurück, so dass es temporäre erstellt, von denen ich Adresse nehme und an f2 überlasse.
Jetzt bitte erklären Sie mir, wo ich falsch denke?

Antwort

5

Die unäre & nimmt einen Lvalue (oder einen Funktionsnamen). Die Funktion f1() gibt keinen Lvalue zurück, sondern gibt einen Rvalue zurück (für eine Funktion, die etwas zurückgibt, es sei denn, sie gibt eine Referenz zurück, ihr Rückgabewert ist ein Rvalue), so dass die unäre & nicht angewendet werden kann.

+0

Aber ich kann f1() so verwenden: f1 (str) = "glücklich"; Hier verwende ich temporär als l-Wert. –

+4

Happy Mittal, das Wort lvalue mag ein wenig verwirrend sein - es bedeutet nicht mehr "ein Wert, der auf der linken Seite einer Aufgabe stehen kann". Wenn Sie den Operator '=' verwenden, rufen Sie tatsächlich eine Elementfunktion des Zeichenfolgenobjekts auf. Sie dürfen Mitglieder von rvalues ​​verwenden. – avakar

+0

Was würde also passieren, wenn String einen expliziten Operator & {return this;} hätte? – user168715

1

Ihr Programm kompiliert nicht, weil f1 einen Parameter hat und Sie keine weitergeben.

Darüber hinaus ist der von einer Funktion zurückgegebene Wert ein rvalue, dessen Adresse Sie nicht verwenden können.

+0

Oh ... Mein schlechtes. Aber es gibt immer noch Warnung: "Adresse von temporären" –

+1

Happy Mittal, ja, weil es ein rvalue ist. Stellen Sie sich vor, dass die Funktion ein 'int' anstelle einer' string' zurückgibt, es kann offensichtlicher sein - der zurückgegebene Wert muss keinen entsprechenden Speicherort haben. – avakar

1

Versuchen Sie folgendes:

int main() 
{ 
    string str; 
    string str2 = f1(str); // copy the temporary 
    f2(&str2); 
} 
+1

Das ist eine unnötige Kopie. (_Wenn es Ihnen nichts ausmacht, Strings unnötigerweise zu kopieren, warum sollten Sie sich überhaupt mit C++ befassen? _) Wenn Sie einen rvalue an eine 'const'-Referenz binden, wird die Lebensdauer des rvalue bis zum Ende der Lebensdauer der Referenz verlängert. Also ist 'const std :: string & str2 = f1 (str);' was du willst. – sbi

+0

@sbi: Mein Beispiel, wie sein, ist viel einfacher als jeder echte Code. – egrunin

+1

Beachten Sie, dass Ihre Antworten den Menschen beibringen sollen, Dinge zu tun, die sie noch nicht wissen. Auch wenn Sie nur etwas auslassen, weil es für Ihre Argumentation nicht relevant ist, können andere dennoch eine falsche Angewohnheit daraus ableiten. – sbi

3

Es ist möglich (und bekommen) einen Zeiger auf ein temporäres Objekt zu erstellen, vorausgesetzt, dass Sie wissen, was Sie tun. Es sollte jedoch anders gemacht werden.

Eine Funktion mit Rückgabewert eines Nicht-Referenztyps gibt rvalue zurück. In C++ ist das Anwenden des eingebauten unären Operators & auf einen R-Wert verboten. Es erfordert einen Lvalue.

Das heißt, wenn Sie einen Zeiger auf Ihr temporäres Objekt erhalten möchten, müssen Sie es auf andere Weise tun. Zum Beispiel, als eine zweizeilige Sequenz

const string &r = f1(str); 
f2(&r); 

die auch

f2(&(const string &) f1(str)); 

In beiden Fällen über der f2 Funktion durch Verwendung einer Guss in eine einzige Linie gefaltet werden können, sollte einen const string * Parameter akzeptieren. Nur ein string * wie in Ihrem Fall wird nicht funktionieren, es sei denn, Sie wegwerfen Konstanz aus dem Argument (was, BTW, wird das Ganze noch hässlicher machen als es bereits ist). Obwohl, wenn der Speicher mir dient, gibt es in beiden Fällen keine Garantie, dass die Referenz an das ursprüngliche temporäre und nicht an eine Kopie angehängt wird.

Denken Sie daran, obwohl das Erstellen von Zeigern auf temporäre Objekte eine eher zweifelhafte Praxis ist, wenn die offensichtliche Lebensdauer Probleme. Normalerweise sollten Sie die Notwendigkeit vermeiden, dies zu tun.