2008-10-18 13 views

Respuesta

15

Primero asegúrese de que realmente necesita apoyar la copia. La mayoría de las veces no es el caso, y por lo tanto deshabilitar ambos es el camino a seguir.

A veces, aún necesitará proporcionar duplicación en una clase de una jerarquía polimórfica, en ese caso: deshabilitar el operador de asignación, escribir un constructor de copia (¿protegido?) Y proporcionar una función virtual clone().

De lo contrario, en el caso de que esté escribiendo una clase de valor, está de regreso en la tierra de la forma canónica ortogonal de Coplien. Si tiene un miembro que no puede copiarse trivialmente, deberá proporcionar un constructor de copia, un destructor, un operador de asignación y un constructor predeterminado. Esta regla puede ser refinada, véase por ejemplo: The Law of The Big Two

También me gustaría recomendar a echar un vistazo a C++ FAQ regarding assignment operators, y al copy-and-swap idiom y al GOTW.

+0

Pensé que se llamaba la regla de 4. –

+0

AFAIK, se origina en el libro de Jim Coplien, de ahí el nombre - Por cierto, solo se aplica a las clases de valores. Algunos lo llaman la regla de cuatro. Hay (¿hubo?) También explicaciones sobre/Rule of Big Three/en C++ FAQ lite (no puedo encontrarlo más). Y se puede reducir a dos gracias a RAII. –

+2

También protege contra la autoasignación en el operador de asignación. –

-2

no tengo ni idea acerca excepción de forma segura aquí, pero voy por aquí. Imaginemos que es una envoltura de matriz modelada. Espero que ayude :)

Array(const Array& rhs) 
    { 
     mData = NULL; 
     mSize = rhs.size(); 
     *this = rhs; 
    } 

    Array& operator=(const Array& rhs) 
    { 
     if(this == &rhs) 
     { 
      return *this; 
     } 

     int len = rhs.size(); 

     delete[] mData; 

     mData = new T[len]; 

     for(int i = 0; i < len; ++i) 
     { 
      mData[i] = rhs[i]; 
     } 

     mSize = len; 

     return *this; 
    } 
+0

Este código no está a salvo excepción. ¡Siempre asigne antes de soltar! –

+0

No, no lo es. No tuve problemas con el código de excepción de seguridad, así que nunca tuve la oportunidad de practicarlo. Este de arriba es solo snipper, normalmente usas contenedores STL. Por favor, publique su fragmento, me gustaría echarle un vistazo. – Nazgob

+0

Hay muchos fragmentos en los enlaces que he proporcionado en mi respuesta. BTW, la prueba que impide la autoasignación se considera ahora como un anti-idioma (ahora que las excepciones se entienden mejor) –

4

Las versiones generadas por el compilador funcionan en la mayoría de las situaciones.

Necesita pensar un poco más sobre el problema cuando su objeto contiene un puntero RAW (un argumento para no tener punteros RAW). Entonces, si tiene un puntero RAW, la segunda pregunta es si posee el puntero (¿está siendo borrado por usted)? Si es así, deberá aplicar la regla de 4.

Poseer más de 1 puntero RAW se vuelve cada vez más difícil de hacer correctamente (El aumento en la complejidad tampoco es lineal [pero eso es observacional y no tengo estadísticas reales para volver a esa declaración]]. Entonces, si tiene más de 1 puntero RAW, piense en envolver cada uno en su propia clase (alguna forma de puntero inteligente).

Regla 4: Si un objeto es el dueño de un puntero RAW entonces es necesario definir los siguientes 4 miembros para asegurarse de que usted maneja la gestión de memoria correctamente:

  • Constructor
  • constructor de copia
  • operador de asignación
  • Destructor

cómo se defina éstas dependerán de la situat iones. Pero las cosas a tener en cuenta:

  • defecto de construcción: Establecer puntero a NULL
  • constructor de copia: utilizar la copia y de intercambio Ideum para proporcionar a la "Garantía de Excepción fuerte"
  • operador
  • Asignación: Check para la asignación a uno mismo
  • Destructor: Protéjase de las excepciones que se propagan fuera del destructor.
+0

"Las versiones generadas por el compilador funcionan en la mayoría de las situaciones". - dependiendo del tipo de programación que hagas. Incluso si todo se trata de indicadores inteligentes, que se ocupan del seguimiento de recursos y los problemas de excepción, una copia superficial puede no ser lo que quiere semánticamente. –

1

intente leer esto.

http://www.icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html

es un muy buen análisis de Operador de asignación

+0

Esto es típicamente lo que preguntaría en una entrevista. Sin embargo, veo una suposición falsa: que la mayoría de los objetos requieren ser copiables. "Cada objeto en un sistema C++ bien diseñado tiene un constructor predeterminado, un constructor de copia y un operador de asignación". Esta oración es para objetos basados ​​en valores, no entidades. –

Cuestiones relacionadas