2011-02-01 32 views
11

Estoy aprendiendo C++, y me he encontrado con el siguiente dilema:Crear referencia al nuevo objeto

Como ++ novato C, he leído que el uso de referencia en lugar de punteros (cuando sea posible) es generalmente una buena idea, así que estoy tratando de acostumbrarme temprano. Como resultado, tengo una gran cantidad de métodos que tienen la forma general de

void myMethod(ParamClass const& param); 

Ahora, me pregunto cuál es la mejor manera de llamar a estos métodos. Por supuesto, cada llamada se necesita un objeto diferente se pasa como parámetro, y por lo que sé que la única manera de crear es el nuevo operador, por lo que ahora estoy haciendo lo siguiente:

myObject.myMethod(*new ParamClass(...)); 

Si bien esto método funciona totalmente, me pregunto si no hay otra "forma C++" ya establecida de hacer esto.

¡Gracias por la ayuda! Dan

+3

haciendo eso, tiene una pérdida de memoria, porque nunca mantendrá el valor del puntero en ninguna parte. – Benoit

+0

El libro, "Programación de la GUI de C++ con Qt 4", tiene un apéndice excelente llamado "Introducción a C++ para programadores Java y C#". Si ese es el fondo desde el que viene, probablemente proporcione un "inicio rápido" eficiente para cambiar algunos de los patrones establecidos entre los idiomas. La mayoría de las bibliotecas pueden obtener una copia usando ILL si no desea comprar el libro. (Si está considerando usar Qt, sin embargo, * obtenga el libro *. –

Respuesta

13

Para empezar, intente no utilizar new, ya que su uso trae problemas para la administración de la memoria.

Para su ejemplo, acaba de hacer lo siguiente:

int main(int, char*[]) 
{ 
    SomeObject myObject; 

    // two phases 
    ParamClass foo(...); 
    myObject.myMethod(foo); 

    // one phase 
    myObject.myMethod(ParamClass(...)); 

    return 0; 
} 

recomiendo el primer método (en dos ocasiones) porque hay trampas sutiles con el segundo.

EDIT: los comentarios no son realmente apropiados para describir los problemas a los que me refería.

Como @Fred Nurk citada, el estándar dice algunas cosas sobre la vida útil de provisionales:

[class.temporary]

(3) Los objetos temporales se destruyen como el último paso en la evaluación la expresión completa (1.9) que (léxicamente) contiene el punto donde fueron creados. Esto es cierto incluso si esa evaluación termina arrojando una excepción. Los cálculos de valor y los efectos secundarios de destruir un objeto temporal están asociados solo con la expresión completa, no con ninguna subexpresión específica.

(5) El temporal al que se vincula la referencia o el temporal que es el objeto completo de un subobjeto al que la referencia está vinculada persiste durante el tiempo de vida de la referencia [nota: excepto en algunos casos ... .]

(5) [como ...] Un límite temporal a un parámetro de referencia en una llamada a función (5.2.2) persiste hasta la finalización de la expresión completa que contiene la llamada.

Esto puede conducir a dos errores sutiles, que la mayoría de los compiladores no cogen:

Type const& bound_bug() 
{ 
    Type const& t = Type(); // binds Type() to t, lifetime extended to that of t 
    return t; 
} // t is destroyed, we've returned a reference to an object that does not exist 

Type const& forwarder(Type const& t) { return t; } 

void full_expression_bug() 
{ 
    T const& screwed = forwarder(T()); // T() lifetime ends with `;` 
    screwed.method(); // we are using a reference to ???? 
} 

Argyrios remendado Clang en mi pedido, por lo que se detecta el primer caso (y algunos más realidad que yo inicialmente no había pensado). Sin embargo, el segundo puede ser muy difícil de evaluar si la implementación de forwarder no está en línea.

+0

¿A qué "refutaciones sutiles" se está refiriendo? Me suena a FUD. –

+1

@Alf: Deseo ... intentar pasar un límite temporal a 'T const & foo (T const & t) {return t;} ', es realmente divertido:/Los límites temporales son un campo de minas para los incautos, y los compiladores están fuera de su alcance cuando se trata de diagnosticar esto. –

+0

@Matthiu: ahora es El FUD abierta y claramente puro, en lo que a mí respecta, no existe tal cosa como "límite temporal". Quizás se refiera a un límite temporal a una referencia, en cuyo caso es lo mismo que pasar una variable (es indistinguible). –

3

Probar: myObject.myMethod(ParamClass(...)); en C++, a diferencia de Java, que no siempre se necesita decir new para crear un nuevo objeto.

1

La forma establecida de hacer es con una variable local automática:

ParamClass myParam; 
myOjbect.myMethod(myParam); 

Mediante el uso de new en la manera que lo hizo, se está generando una pérdida de memoria. Nada se deshará de ese objeto una vez que la función regrese - C++ no tiene recolección de basura como lo hacen otros lenguajes.

0

Debe tener en cuenta la vida útil del objeto. Si pasa *new ParamClass a una función, está cediendo la propiedad del nuevo objeto a la función. Si la función no la destruye (y nunca debería hacer eso dada una referencia), obtendrá una pérdida de memoria.

su lugar, debe hacer algo como esto:

ParamClass myParamClass(...); 
myObject.myMethod(myParamClass); 
0

Cuando se escribe

myObject.myMethod(*new ParamClass(...)); 

se pierde el puntero al objeto new'd. Es decir, esto funcionará, pero no podrá más tarde delete el objeto. Así que usted puede hacer esto:

ParamClass pc(...); 
myObject.myMethod(pc); 

o, más fácil

myObject.myMethod(ParamClass(...)); 

o, si la asignación dinámica es necesario por alguna razón inexplicable

ParamClass* pPc = new ParamClass(...); 
myObject.myMethod(*pPc); 
... 
delete pPc; 

o, utilizar punteros inteligentes para evitar la eliminación manual . Algo así como:

boost::scoped_ptr<ParamClass> spPc(new ParamClass(...)); 
myObject.myMethod(*pPc); 

Esperanza esto ayuda

0

Sólo tenga en cuenta que no hay gran diferencia entre la asignación del valor de un objeto (me refiero al objeto de la clase definida por el usuario) creado con anterioridad a nuevo objeto en Java y C++ , y se trata de:

1- en C++: objeto nueva = (objeto) mayores [crear una copia del objeto más antiguo a más reciente y cuando se modifica más nuevo, el más viejo no lo hará cambiar]

2- en Java: objetos nueva = (objeto) mayores [crear una referencia al objeto mayor y cuando se modifica el más nuevo, el mayor también lo hará cambio (muy muy importante)]

conclusión:

en java: "objeto nuevo = (objeto) mayor" es el mismo que "objeto & nuevo = (objeto) mayor" en C++.

Cuestiones relacionadas