2010-05-01 19 views
15

Estaba reflexionando sobre la cantidad de preguntas aquí que se refieren a los "tres grandes" (copia constructor, operador de asignación y destructor) o sobre problemas causados ​​por que no se implementaron correctamente, cuando se me ocurrió que no podía Recuerdo la última vez que los implementé yo mismo. Un rápido grep en mis dos proyectos más activos indica que implemento los tres en una sola clase de alrededor de 150.¿Con qué frecuencia implementa los tres grandes?

Eso no quiere decir que no implemente/declare uno o más de ellos, obviamente las clases base necesitan un virtual destructor, y un gran número de mis clases prohíben copiar utilizando la copia privada del ctor & asignación op idiom. Pero completamente implementado, existe esta única clase solitaria, que hace un recuento de referencias.

Así que me preguntaba ¿soy inusual en esto? ¿Con qué frecuencia implementa las tres funciones? ¿Hay algún patrón en las clases donde los implemente?

+2

¡Leer esta pregunta me hace tan feliz que no tengo que escribir C++! (Por supuesto, esto probablemente explica por qué tengo dificultades para modificar C++ de otras personas). –

+6

-1 @Norman No hay necesidad de ir en contra de C++. Si no tiene que escribir el código C++ vaya a otra pregunta. Nunca he entendido a la gente que, debido a que no usan algo, lo que quieren es que nadie lo use, y viceversa. –

+4

@Norman Lo hubiera pensado (y las respuestas) son alentadores: muy rara vez necesita hacer una tarea compleja. –

Respuesta

2

Creo que es raro que necesite las tres. La mayoría de las clases que requieren un destructor explícito no son realmente adecuadas para la copia.

Es mejor diseñar para usar miembros autodestructivos (que normalmente no requieren cosas como la construcción de copias) que un gran destructor explícito.

+0

El idioma pImpl es un contraejemplo comúnmente utilizado. –

+0

std :: auto_ptr maneja eso. – Puppy

+0

DeadMG: ¿estás seguro? – Joshua

1

Como usted, casi nunca.

Pero no estoy vinculado al enfoque STL de la programación en el que se copia todo en contenedores: generalmente, si no es un primitivo, usaré un puntero, inteligente o no.

Principalmente utilizo patrones RAII, así evito escribir destructores. Aunque, pongo cuerpos vacíos en mi archivo .cc para ayudar a mantener el código inflado.

Y, como usted, declararé que son privadas y no implementadas para evitar cualquier invocación accidental.

+4

¿Eh? Los destructores son la piedra angular de RAII. ¿O quiso decir que utiliza exclusivamente clases RAII escritas por otros? –

+0

Los cuerpos de funciones vacías causan menos hinchamiento de código si están en el archivo de cabecera para que puedan estar en línea. Pero no puedo imaginarme por qué definir un destructor vacío. – Potatoswatter

+0

@Ben Voigt, obviamente sí, los destructores son fundamentales para raii ... pero normalmente no necesito escribir mis propias clases de RAII, y cuando uso miembros de Ravi, no necesito limpiarlos en destructores. – Stephen

1

Raramente los implemento, pero a menudo los declaro privados (es decir, constructores de copia y operadores de asignación).

0

La mayoría de las veces, casi nunca. Esto se debe a que los miembros que se usan (ptr inteligente basado en referencia, etc.) ya implementan la semántica adecuada o el objeto no se puede copiar.

Unos patrones surgen cuando me encuentro la aplicación de estas:

  1. copia destructiva, es decir, patrón de movimiento como auto_ptr o bloquear
  2. patrón de disponer que casi todos los sube en C++, pero que he usado es alrededor de tres veces en mi carrera (y hace una semana, de hecho)
  3. patrón de pimpl, donde el pimpl se declaró fwd en el encabezado, y administrado por un ptr inteligente. A continuación, el dtor vacía va en el archivo .cc pero todavía clasifica como "no compilador genera"

Y otra trivial que imprime "fui destruido" cuando yo creo que tengo una referencia circular en alguna parte y sólo quieren asegurarse.

0

Realmente depende del tipo de problema en el que esté trabajando. He estado trabajando en un nuevo proyecto en los últimos meses y creo que cada clase hereda de boost :: noncopyable. Hace nueve meses trabajé en un proyecto diferente que usaba POD bastante y aproveché el copiador automático y el operador de asignación.Si está utilizando boost :: shared_ptr (y debería estarlo), en la actualidad no debería escribir su propio copiador u operador de asignación.

0

Cualquier clase que posea algunos miembros de punteros debe definir estas tres operaciones para implementar una copia en profundidad (consulte here para obtener una descripción detallada).

+0

No se trata de ser dueño de los indicadores, sino de poseer lo que señalan. Una clase puede contener un puntero sin propiedad, y en ese caso probablemente no necesite los tres grandes. Y estoy muy en contra del término "copia profunda" - hay solo un tipo de operación de copia - la correcta. –

+0

@Neil Butterworth: Usted ha comentado previamente una respuesta mía que el término "copia profunda" no es de mucha utilidad. (Consulte aquí: http://stackoverflow.com/questions/2657810/2657824#2657824) En ese otro hilo no dijo explícitamente que "solo hay un tipo de operación de copia, la correcta". Tengo curiosidad: ¿cuál sería eso? ¿El correcto en un caso particular, o una solución general? – stakx

+0

@stakx El correcto para la clase en particular, que puede ser profundo, poco profundo o más probable en algún punto intermedio. –

Cuestiones relacionadas