2010-07-26 7 views
5

En C++, ff tengo una clase que necesita para mantener un miembro que puede ser asignada dinámicamente y se utiliza como un puntero, o no, como este:miembros de la clase dinámicos vs no dinámica

class A { 
    type a; 
}; 

o

class A { 
    A(); 
    ~A(); 
    type* a; 
}; 

y en el constructor:

A::A { 
    a = new type(); 
} 

y destructor:

A::~A { 
    delete a; 
} 

¿Hay alguna ventaja o desventaja en una u otra, además de la dinámica que requiere más código? ¿Se comportan de manera diferente (aparte de que el puntero debe ser desreferenciado) o es uno más lento que el otro? ¿Cuál debería usar?

+2

Trabaja para tener un código de mantenimiento correcto, y luego si es necesario, trabaja en el rendimiento. –

+1

Su segundo 'A' no es seguro; necesita definir el constructor de copia y 'operator =' también. Nunca tengas apuntadores como esos, envuélvelos para que no necesites escribir * ninguna * función especial para miembros. – GManNickG

Respuesta

0

Con el puntero tiene más control, pero también más responsabilidades. Usted tiene más control en el sentido de que puede decidir la vida útil del objeto de manera más precisa, mientras que sin el puntero la duración es esencialmente igual a la vida útil del objeto que lo contiene. Además, con el puntero, el miembro podría ser una instancia de una subclase del tipo de puntero.

En lo que respecta a rendimiento, utilizar el puntero significa más uso de memoria, más fragmentación de memoria y eliminar referencias requiere bastante tiempo. Sin embargo, para todo menos para el código de mayor rendimiento no vale la pena preocuparse por nada de esto.

0

La diferencia principal es que el puntero puede apuntar potencialmente a otro lugar.

edición

respuesta de Laurence no está mal, pero es un poco general. En específico, la asignación dinámica será un poco más lenta. La desreferencia a través del puntero también será muy levemente más lenta. Una vez más, no se trata de una gran pérdida de velocidad, y la flexibilidad que compra puede valer la pena.

0

La diferencia principal es que si no usa un puntero, la memoria para el miembro interno se asignará como parte de la memoria asignada para el objeto que lo contiene. Si usa new, obtendrá memoria en trozos separados (parece que ya ha creado y destruido correctamente el objeto al que se hace referencia)

0

Necesita comprender las implicaciones del constructor de copia predeterminado y los operadores de asignación de copia al usar punteros sin procesar . El puntero sin formato se copia en ambos casos. En otras palabras, terminará teniendo varios objetos (o punteros sin procesar) apuntando a la misma ubicación de memoria. Por lo tanto, su destructor escrito como está arriba intentará eliminar la misma memoria varias veces.

5

hay varias diferencias:

  1. El tamaño de cada miembro debe ser conocida cuando se está definiendo una clase. Esto significa que debe incluir su encabezado type y no puede usar una declaración directa como lo haría con un miembro de puntero (dado que se conoce el tamaño de todos los punteros). Esto tiene implicaciones para #include clutter y tiempos de compilación para proyectos grandes.

  2. La memoria para el miembro de datos es parte de la instancia de clase envolvente, de manera, que se asignará al mismo tiempo, en el mismo lugar, como todos los otros miembros de la clase (ya sea en la pila o el montón) Esto tiene implicaciones para la ubicación de los datos: tener todo en el mismo lugar podría conducir a una mejor utilización de la memoria caché, etc. La asignación de la pila probablemente será un poco más rápida que la asignación de la pila. Declarar demasiadas instancias de objetos enormes podría explotar tu pila más rápido.

  3. El tipo de puntero es más complicado de gestionar, ya que no se asigna o destruye automáticamente junto con la clase, debe asegurarse de hacerlo usted mismo. Esto se vuelve complicado con múltiples miembros de puntero: si está new ing todos ellos en el constructor, ya la mitad del proceso hay una excepción, el destructor no se llama y tiene una pérdida de memoria. Es mejor asignar variables de puntero a un contenedor de "puntero inteligente" (como std::auto_ptr) inmediatamente, de esta manera la limpieza se maneja automáticamente (y no necesita preocuparse por delete entrándolas en el destructor, lo que a menudo le ahorra escribir uno en absoluto). Además, cada vez que maneja recursos manualmente, debe preocuparse por los constructores de copias y los operadores de asignación.

+0

Agregar contenedores de puntero inteligente: incluye (stl/boost) para su proyecto generalmente aumenta su tiempo de compilación mucho más que incluir sus propios archivos de encabezado. La asignación de la pila, que se considera barata, es mucho más rápida que las asignaciones de pila (que se consideran caras). ¿Por qué tendría que preocuparse por los constructores de copias y los operadores de asignación si está manejando los recursos manualmente? Asegúrese de mantener punteros a ellos en lugar de copiarlos. (simplemente declare la copia/asignación como privada y nunca cometerá el error de hacer el mal). – Simon

0

Si la variable miembro debe vivir más allá del tiempo de vida del objeto, o si su propiedad debe ser transferido a otro objeto, entonces el miembro debe ser dinámicamente (montón) asignado usando "nueva". Si no es así, a menudo es la mejor opción convertirlo en un miembro directo de la clase para simplificar el código y disminuir la carga en el asignador de memoria. La asignación de memoria es costosa.

Cuestiones relacionadas