2010-06-06 7 views
5

Probé siguiente código:Pass objeto temporal de función que toma puntero

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

Pero este código no compila.
Lo que creo es: f1 regresa por valor, por lo que crea temporal, de lo cual estoy tomando la dirección y pasando a f2.
Ahora, por favor, ¿me explico dónde estoy pensando que está mal?

Respuesta

5

El unario & toma un valor izquierdo (o un nombre de función). Función f1() no devuelve un valor izquierdo, devuelve un valor de lado derecho (para una función que devuelve algo, a menos que devuelve una referencia, su valor de retorno es un valor p), por lo que el unario & no se puede aplicar a la misma.

+0

Pero puedo usar f1() de esta manera: f1 (str) = "feliz"; Aquí estoy usando temporal como l-value. –

+4

Happy Mittal, la palabra lvalue puede ser un poco confusa, ya no significa "un valor que puede pararse en el lado izquierdo de una tarea". cuando utiliza el operador '=', de hecho está llamando a una función miembro del objeto de cadena. Puede usar miembros de valores. – avakar

+0

Entonces, ¿qué pasaría si string tuviera un operador explícito y {return this;}? – user168715

1

Su programa no compilará porque f1 tiene un parámetro y usted no está pasando ninguna.

Además, el valor devuelto por una función es un valor de lado derecho, no se puede tomar su dirección.

+0

Oh ... Mi mal. Pero todavía está dando advertencia: "tomando la dirección de temporal" –

+1

Happy Mittal, sí, porque es un valor r. Imagine que la función devuelve un 'int' en lugar de una' cadena', puede ser más obvio: el valor que se devuelve no necesita tener ninguna ubicación de memoria correspondiente. – avakar

1

Prueba esto:

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

Esa es una copia innecesaria. (_Si no le molesta copiar cadenas innecesariamente, ¿para qué molestarse con C++? _) Si vincula un valor r a una referencia 'const', la duración del rvalue se extenderá hasta el final de la vida útil de la referencia. Entonces 'const std :: string & str2 = f1 (str);' es lo que quiere. – sbi

+0

@sbi: Mi ejemplo, como el suyo, es mucho más simple que cualquier código del mundo real. – egrunin

+1

Tenga en cuenta que sus respuestas son para enseñar a las personas cómo hacer cosas que aún no conocen. A pesar de que solo omites algo porque no es relevante para tu argumento, otros aún pueden tomar un hábito equivocado de él. – sbi

3

Es posible crear (y pasar) un puntero a un objeto temporal, asumiendo que usted sabe lo que está haciendo. Sin embargo, debe hacerse de manera diferente.

Una función con valor de retorno de tipo no de referencia devuelve rvalue. En C++, se prohíbe aplicar el operador unario incorporado & a un valor r. Requiere un lvalue

Esto significa, que si se quiere obtener un puntero a su objeto temporal, hay que hacerlo de alguna otra manera. Por ejemplo, como una secuencia de dos líneas

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

que también se puede plegar en una sola línea mediante el uso de un molde

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

En ambos casos anteriores la función f2 debe aceptar un parámetro const string *. Solo un string * como en su caso no funcionará, a menos que elimine la constness del argumento (lo que, por cierto, hará que todo sea aún más feo de lo que ya es). Aunque, si me sirve la memoria, en ambos casos no hay garantía de que la referencia se adjunte al original temporal y no a una copia.

Hemos de tener en cuenta, sin embargo la creación de punteros a objetos temporales es una práctica bastante dudosa ya que si los problemas de toda la vida obvias. Normalmente deberías evitar la necesidad de hacer eso.

Cuestiones relacionadas