2012-02-15 8 views
7

Cuando quiero crear una instancia de una clase en C++ por lo general voy de esta maneraC++ puntero y de referencia con la nueva palabra clave al crear instancias de

Book bk = new Book(); 

Mi profesor recientemente hizo esto

Book &bk = *new Book(); 

Sólo me dijo que usaría una referencia para poder usar el operador de punto (por ejemplo, bk.getTitle();) en lugar de flecha (por ejemplo, bk-> getTitle();). Entiendo esta parte del código, pero ¿qué sucede cuando usa el operador * en combinación con el nuevo?

Gracias de antemano

el código de ejemplo completo se puede encontrar here es el ArrayStack en la función principal

+7

Así que su profesor le mostró cómo perder memoria, genial. – ildjarn

+2

Si su profesor utiliza ese código para cualquier cosa que no sea como un ejemplo de algo que realmente no debería hacer, entonces debe encontrar un nuevo profesor. –

+0

Probablemente su profesor dijo, 'const Book & bk = Book();'. Si ese no es el caso, honestamente no entiendo lo que su profesor quiso decir. – Mahesh

Respuesta

15

Este:

Book &bk = *new Book(); 

es más o menos equivalente a este:

Book *p = new Book(); // Pointer to new book 
Book &bk = *p; // Reference to that book 

Pero hay una diferencia crucial; en el código original, no tiene un puntero que pueda usar para delete el objeto asignado dinámicamente cuando haya terminado con él, por lo que ha creado efectivamente una pérdida de memoria.

Por supuesto, usted puede hacer esto:

delete &bk; 

pero eso es muy no idiomática C++, y muy probable que cause problemas más adelante.

En resumen, no hay absolutamente ninguna buena razón para escribir código como este, por lo que no lo haga. Cualquiera de los siguientes está bien:

Book bk; 
Book bk = Book(); 
+0

gracias, creo que no lo usaré en ese momento. La clase trata más sobre patrones de diseño que sobre C++, así que simplemente ignoraré este estilo de programación y lo haré a mi manera. – tim

+1

Definitivamente no ha creado una pérdida de memoria, creo que es una gran exageración –

+0

@Seth: El código original sí tiene una fuga ... ¿Qué quiere decir? – ildjarn

0

He encontrado una situación que me permite pensar en esa sintaxis. Considere un puntero inteligente a una clase Base y que debe contener un puntero a una clase derivada y le gustaría acceder a algunas cosas no virtuales de la clase derivada después de la construcción. En este caso algo como esto es legal y puede que no sea tan malo:

Derived & d = * new Derived(); 

d.d_method(..whatever..); 
d.d_member = ..whatever..; 
... 

std::unique_ptr<Base> p(&d); 

Finalmente todavía prefieren las pequeñas flechas a los símbolos de unión extraños:

Derived d = new Derived(); 

d->d_method(..whatever..); 
d->d_member = ..whatever..; 
... 

std::unique_ptr<Base> p(d); 

Pero creo que en este caso es solo una cuestión de gusto, especialmente si accede a una cantidad constante de métodos.

Otras cosas que conducen a fugas o delete &d; son simplemente malas, malas, malas.

Cuestiones relacionadas