2010-06-06 4 views
5

j'ai essayé code suivant:Passe objet temporaire à la fonction qui prend pointeur

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

Mais ce code ne compile pas.
Ce que je pense est: f1 renvoie en valeur afin qu'il crée temporaire, dont je prends l'adresse et passant à f2.
Maintenant S'il vous plaît expliquez-moi où je pense mal?

Répondre

5

L'unaire & prend une valeur l (ou un nom de fonction). La fonction f1() ne retourne pas de valeur lvalue, elle renvoie une valeur rvalue (pour une fonction qui renvoie quelque chose, sauf si elle renvoie une référence, sa valeur de retour est une valeur rvalue), donc l'unaire & ne peut pas lui être appliqué.

+0

Mais je suis capable d'utiliser f1() comme ceci: f1 (str) = "happy"; Ici j'utilise temporaire comme l-valeur. –

+4

Heureux Mittal, le mot lvalue peut être un peu confus - il ne signifie plus "une valeur qui peut rester sur le côté gauche d'une affectation". lorsque vous utilisez l'opérateur '=', vous appelez en fait une fonction membre de l'objet chaîne. Vous êtes autorisé à utiliser des membres de rvalues. – avakar

+0

Alors, que se passerait-il si la chaîne avait un opérateur explicite & {return this;}? – user168715

1

Votre programme ne compile pas car f1 a un paramètre et vous n'en transmettez aucun.

En outre, la valeur renvoyée par une fonction est une valeur, vous ne pouvez pas prendre son adresse.

+0

Oh ... Mon mauvais. Mais il est encore donner un avertissement: "prendre l'adresse de temporaire" –

+1

Heureux Mittal, oui, parce que c'est une valeur. Imaginez la fonction retournant un 'int' au lieu d'un' string', cela peut être plus évident - la valeur retournée n'a pas besoin de l'emplacement mémoire correspondant. – avakar

1

Essayez ceci:

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

C'est une copie inutile. (_Si cela ne vous dérange pas de copier inutilement des chaînes, pourquoi s'embêter avec C++? _) Si vous liez un rvalue à une référence 'const', la durée de vie de rvalue sera étendue à la fin de la vie de la référence. Donc 'const std :: string & str2 = f1 (str);' est ce que vous voulez. – sbi

+0

@sbi: Mon exemple, comme le sien, est beaucoup plus simple que n'importe quel code réel. – egrunin

+1

Notez que vos réponses sont d'apprendre aux gens à faire des choses qu'ils ne connaissent pas encore. Même si vous omettez quelque chose parce que ce n'est pas pertinent pour votre argument, d'autres peuvent toujours prendre une mauvaise habitude. – sbi

3

Il est possible de créer (et passer) un pointeur vers un objet temporaire, en supposant que vous savez ce que vous faites. Cependant, cela devrait être fait différemment.

Une fonction avec une valeur de retour de type sans référence renvoie rvalue. En C++, l'application de l'opérateur unaire intégré & à une valeur est interdite. Cela nécessite une lvalue.

Cela signifie que si vous voulez obtenir un pointeur vers votre objet temporaire, vous devez le faire d'une autre manière. Par exemple, en tant que séquence de deux lignes

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

qui peut également être pliée en une seule ligne à l'aide d'un plâtre

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

Dans les deux cas ci-dessus la fonction f2 doit accepter un paramètre const string *. Juste un string * comme dans votre cas ne fonctionnera pas, sauf si vous rejetez constness de l'argument (ce qui, BTW, rendra le tout encore plus laid que ce qu'il est déjà). Bien que, si ma mémoire est bonne, dans les deux cas, il n'y a aucune garantie que la référence est attachée à l'original temporaire et non à une copie. Gardez à l'esprit que la création de pointeurs vers des objets temporaires est une pratique plutôt douteuse car si les problèmes de durée de vie sont évidents. Normalement, vous devriez éviter de devoir faire cela.

Questions connexes