¿Cuál es la forma más confiable de prohibir un constructor de copia en C ++?

A veces es necesario prohibir un constructor de copia en una clase de C ++ para que la clase se convierta en “no copiable”. Por supuesto, operator= debería estar prohibido al mismo tiempo.

Hasta ahora he visto dos formas de hacer eso. La forma 1 es declarar el método como privado y no darle ninguna implementación:

 class Class { //useful stuff, then private: Class( const Class& ); //not implemented anywhere void operator=( const Class& ); //not implemented anywhere }; 

La forma 2 es declarar el método como privado y darle la implementación “vacía”:

 class Class { //useful stuff, then private: Class( const Class& ) {} void operator=( const Class& ) {} }; 

IMO, el primero es mejor, incluso si hay alguna razón inesperada que conduzca al llamado al constructor de copia desde la misma función de miembro de la clase, habrá un error de enlazador más adelante. En el segundo caso, este escenario no se detectará hasta el tiempo de ejecución.

¿Hay algún inconveniente serio en el primer método? ¿Cuál es una mejor manera si hay alguna y por qué?

El primer método es cómo Boost lo resuelve ( código fuente ), hasta donde yo sé, no hay inconvenientes. De hecho, los errores del enlazador son la gran ventaja de ese método. Desea que los errores estén en tiempo de enlace, no cuando su cliente está ejecutando su código y de repente se bloquea.

En caso de que esté utilizando Boost, puede ahorrarse algo de tipeo. Esto hace lo mismo que tu primer ejemplo:

 #include  class Class : boost::noncopyable { // Stuff here } 

El primero es mejor

Aún mejor es C ++ 0x palabra clave ‘eliminar’ :

 class Class { // useful stuff, then public: Class(const Class&) = delete; void operator=(const Class&) = delete; }; 

Siempre puede heredar de boost::noncopyable .

De lo contrario, nunca he visto una razón por la que el número 2 sea mejor que el número 1, ya que le permitirá “copiar y construir” un objeto dentro de los métodos friend o class, aunque en realidad no cree una copia verdadera del objeto.

Como otras respuestas sugieren algo más, y realmente no intenta responder a la pregunta, este es mi bash:

Entonces, ¿qué enfoque es mejor? Depende de cómo defina la copia prohibida ?

Si desea evitar que otros (solo las clases y funciones que no son de amigos) copien mientras permite que los amigos y las funciones de los miembros copien , el segundo enfoque es el camino a seguir.

Si desea evitar que todos (amigos, no amigos, miembros de funciones) copien, entonces el primer enfoque es la única solución correcta.

Tenga en cuenta que el segundo enfoque no impide que amigos y funciones miembro copien (es decir, que no llamen a las funciones de copia) . 1

1. Si no los define adecuadamente en el segundo caso, entonces la copia no funcionaría, como se esperaba, pero eso es completamente diferente. Pero el punto es que el segundo caso no impide llamar a las funciones de copia. El comstackdor no generaría ningún mensaje de error.

No hay inconveniente en su primer enfoque, lo he estado usando para hacer una clase “no copiable”.

Personalmente, creo que ha respondido su propia pregunta y debería usar el primer enfoque.

Si no desea que se pueda copiar, como dijo, generará un error de enlazador. Sin embargo, si utilizas el segundo método y terminas utilizando el constructor de copias por accidente, SE COMPARARÁ y se ejecutará; y no tendrá absolutamente ninguna indicación de dónde salió la inconsistencia hasta que abra un depurador. O como dijo, si puede usar un comstackdor moderno, use la notación ‘= delete’ de C ++ 11.