2011-04-14 7 views
10

Possible Duplicate:
warning: returning reference to temporaryC++ Volviendo referencia al temporal

estoy consiguiendo el error "volver referencia a temporal" en la segunda línea de abajo.

class Object : public std::map <ExString, AnotherObject> const { 
public: 
const AnotherObject& Find (const ExString& string) const { 
    Object::const_iterator it = find (string); 
    if (it == this->end()) { return AnotherObject() }; 
    return (it->second); 
} 
} 

Mi clase implementa std :: map.

Soy nuevo en C++, así que supongo que es solo un error de sintaxis. ¿Alguna ayuda?

+1

¿Cuál es la firma de función en la que se encuentra el código? ¿O cuál es el contexto de ese código? – Xeo

+0

Completé un poco más detalles – dcinadr

Respuesta

3

Está creando un valor temporal en la pila AnotherObject() y lo devuelve justo antes de que se destruya. La persona que llama a su función recibiría basura, por lo que está prohibida.

¿Quizás desea asignarlo en el montón y devolver un puntero a él en su lugar?

return new AnotherObject(); 

Alternativamente, declare su función para devolver una "copia" a su objeto, en lugar de una referencia que estoy asumiendo que usted está volviendo ahora mismo:

AnotherObject f() 
{ 
    return AnotherObject(); // return value optimization will kick in anyway! 
} 
+0

O tal vez desea devolverlo por valor. Ese suele ser el caso (pero obviamente depende de la semántica de 'AnotherObject'). –

+0

¡Ha pasado un buen rato desde que toqué C++, pero todavía adiviné la parte de referencia! – Blindy

+0

return new AnotherObject() no funciona. Obtengo un error: invalide la referencia de inicialización del tipo 'const AnotherObject &' de la expresión de tipo 'AnotherObject *' – dcinadr

15

Si su función es el siguiente :

AnotherObject& getAnotherObject() 
{ 

    . . . 

    Object::const_iterator it = find ("lang"); 
    if (it == this->end()) { return AnotherObject() }; 

    . . . 

} 

el problema es que el otroObjeto() que haya regresado será destruida tan pronto como se cierra la función, por lo que la persona que llama a la función tendrá una referencia a un objeto falso.

Si su función devuelta por valor de al menos:

AnotherObject getAnotherObject() 

continuación, se hará una copia antes se destruye el original y todo irá bien.

+0

Gran respuesta. Solo para agregar, debes tener cuidado con las fugas en dicha función si estás usando 'new'. Debería envolverlos en 'auto_ptr' o' shared_ptr' para evitar que haga fugas descuidadas. – lxcid

6

return AnotherObject(); crea un objeto que se destruye antes de la salida de la función - los temporales se destruyen al final de la expresión que los contiene [*], y la expresión AnotherObject() crea un temporal.

Dado que la función devuelve por referencia, esto significa que si la persona que llama tiene la oportunidad de ver esa referencia, ya no hace referencia a un objeto válido.

Estaría bien si la función devolviera el valor, ya que el temporal se copiaría [**].

[*] Con un par de situaciones que no, pero no te ayudan aquí.

[**] En realidad, existe una optimización llamada "elisión del constructor de copia", lo que significa que no es necesario crear, copiar ni destruir temporariamente. En cambio, bajo ciertas condiciones, el compilador solo puede crear el destino de la copia de la misma manera que habría haber creado el temporal, y no molestarse con el temporal en absoluto.

1

La función debe declararse para devolver una referencia, y una referencia debe hacer referencia a un objeto que continuará existiendo después de que la función finalice. Su "AnotherObject()" temporal se destruye inmediatamente después de la devolución, por lo que obviamente no funcionará. Si no puede cambiar la firma del método, puede que necesite lanzar una excepción en lugar de devolver un valor de error.

1

Debe cambiar el tipo de devolución de su función de "AnotherObject &" a "AnotherObject" y devolver ese objeto por valor. De lo contrario, funcionará como Blindy describió

0

La llamada al constructor de AnotherObject crea una nueva instancia en la pila, que se destruye inmediatamente cuando el método retorna.

Es muy probable que no sea una buena idea crear y devolver un nuevo objeto si falla el descubrimiento. El código de llamada no tendrá forma de saber si el objeto devuelto es un objeto previamente existente presente en la estructura de datos.

Si desea hacer esto, entonces debe agregar el nuevo objeto a la estructura de datos y luego devolver un iterador que apunta al nuevo objeto EN LA ESTRUCTURA DE DATOS.

Algo como esto:

if (it == this->end()) { 
    it = this->insert(pair<ExString, AnotherObject>(string, AnotherObject())); 
    return it->second; 
}  
+0

¿Me puede dar un ejemplo de esto? – dcinadr

+0

@dcinadr Ejemplo agregado al código. – ravenspoint

0

No debe devolver una referencia a un temporal que se destruye al final de la línea, ni una referencia a un local que se destruye al final de la función .

Si desea conservar la firma actual, deberá agregar una instancia de constante estática que puede devolver de forma predeterminada.

#include <iostream> 

template <class T> 
class X 
{ 
    T value; 
    static const T default_instance; 
public: 
    X(const T& t): value(t) {} 
    const T& get(bool b) const 
    { 
     return b ? value : default_instance; 
    } 
}; 

template <class T> 
const T X<T>::default_instance = T(); 

int main() 
{ 
    X<int> x(10); 
    std::cout << x.get(true) << ' ' << x.get(false) << '\n'; 
} 

También puede devolver por valor o devolver un puntero en cuyo caso puede devolver NULO.

0

Personalmente creo que esto es un poco hackeo, pero siempre y cuando se apegue a la const'ness de la referencia devuelta, debería poder devolver una instancia estáticamente construida de AnotherObject cuyo único "raison d ' etre "debe ser el valor de retorno" no encontrado "de su función. Conviértalo en un miembro privado const static de su clase Object por ejemplo, y debería estar bien siempre que una instancia construida por defecto de AnotherObject no sea un valor válido para contener en una instancia de Object.

Cuestiones relacionadas