funciones fuente ejemplos codigos codigo cadenas basicos arreglos c++ copy-constructor noncopyable

fuente - funciones en c++



¿Cómo hago para que este objeto de C++ no pueda copiarse? (10)

Ver titulo

Yo tengo:

class Foo { private: Foo(); public: static Foo* create(); }

¿Qué debo hacer desde aquí para que Foo no pueda copiarse?

¡Gracias!


En C ++ 11, puede deshabilitar explícitamente la creación del constructor de asignación y copia predeterminado colocando = delete después de la declaración.

De Wikipedia :

struct NonCopyable { NonCopyable() = default; NonCopyable(const NonCopyable&) = delete; NonCopyable & operator=(const NonCopyable&) = delete; };

Lo mismo ocurre con las clases, por supuesto.


Esto es lo que uso:

/* Utility classes */ struct NoCopy { public: NoCopy() {} private: NoCopy(const NoCopy &); }; struct NoAssign { private: NoAssign &operator=(const NoAssign &); }; struct NonInstantiable { private: NonInstantiable(); }; struct NoCopyAssign : NoCopy, NoAssign { }; typedef NoCopyAssign NoAssignCopy;

En tu caso:

struct Example : NoCopy { };


Hacer el constructor de copia privado.

Foo(const Foo& src);

No necesita implementarlo, simplemente declararlo en el archivo de encabezado.


Haga que el constructor de copia y el operador de asignación también sean privados. Solo la declaración es suficiente, no tiene que proporcionar una implementación.



La forma típica de hacer que un objeto de C ++ no pueda copiarse es declarar explícitamente un constructor de copia y un operador de asignación de copia pero no implementarlos. Esto evitará que el compilador genere su propio. (Por lo general, esto se hace junto con declararlos private para que genere un error de compilación en lugar de un error del vinculador).

También está la clase boost::noncopyable la que puedes heredar, que hace lo que describí anteriormente.


Para añadir un poco allí.

La solución tradicional es, como se ha dicho, declarar que tanto Copy Constructor como Assignment Operator son private , y no definirlos .

  • Debido a que son private , esto provocará un error en el tiempo de compilación de cualquiera que intente usarlos y que no tenga acceso a las partes privadas de la clase ...
  • Lo que deja a los amigos (y a la clase en sí) por los cuales se producirá el error bajo la forma de undefined symbol , ya sea en el momento del enlace (si los verifica) o muy probablemente en el tiempo de ejecución (cuando se intenta cargar la biblioteca) .

Por supuesto, es bastante molesto en el segundo caso porque luego tiene que verificar su código usted mismo ya que no tiene la indicación del archivo y la línea en la que se produce el error. Afortunadamente está limitado a tus métodos de clase y amigos.

Además, vale la pena señalar que estas propiedades son transitivas en la ruta de la herencia y la composición: el compilador solo generará versiones Default Constructor , el Copy Constructor , el Assignment Operator y el Destructor si es posible.

Esto significa que para cualquiera de esos cuatro, se generan automáticamente solo si son accesibles para todas las bases y atributos de la clase.

// What does boost::noncopyable looks like > class Uncopyable { public: Uncopyable() {} private: Uncopyable(const Uncopyable&); Uncopyable& operator=(const Uncopyable&); };

Esta es la razón por la que la herencia de esta clase (o su uso como un atributo) efectivamente impide que su propia clase pueda copiarse o asignarse a menos que usted mismo defina esos operadores.

En general, la herencia se elige sobre la composición por 2 razones:

  • El objeto es efectivamente Uncopyable , incluso si el polimorfismo puede no ser tan útil
  • La herencia conduce a EBO o a la Empty Base Optimization , mientras que un atributo será direccionable y, por lo tanto, ocupará memoria (en cada instancia de la clase) incluso si en realidad no lo necesita, el compilador tiene la posibilidad de no agregar esta sobrecarga para una base clase.

Como alternativa, podría declarar a los operadores como privados y no definirlos en su propia clase, pero el código sería menos autodocumentado y no podría buscar automáticamente esa clase que tenga esta propiedad (a menos que tenga un analizador en toda regla).

Espero que esto arroje algo de luz sobre el mecanismo.


Solo otra manera de rechazar el constructor de copias, por conveniencia, se puede usar una macro DISALLOW_COPY_AND_ASSIGN:

// A macro to disallow the copy constructor and operator= functions // This should be used in the private: declarations for a class #define DISALLOW_COPY_AND_ASSIGN(TypeName) / TypeName(const TypeName&) = delete; / void operator=(const TypeName&) = delete

Luego, en clase Foo:

class Foo { public: Foo(int f); ~Foo(); private: DISALLOW_COPY_AND_ASSIGN(Foo); };

ref de la hoja de estilo de google


#include <boost/utility.hpp> class Foo : boost::noncopyable {...

Pero como Scott Meyers dijo una vez: "Es una buena clase, es solo que encuentro el nombre un poco errado, no natural", o algo así.


class Foo { private: Foo(); Foo( const Foo& ); // non construction-copyable Foo& operator=( const Foo& ); // non copyable public: static Foo* create(); }

Si está usando boost, también puede heredar de no copiable: http://www.boost.org/doc/libs/1_41_0/boost/noncopyable.hpp

EDIT: versión C ++ 11 si tiene un compilador que soporta esta característica:

class Foo { private: Foo(); Foo( const Foo& ) = delete; // non construction-copyable Foo& operator=( const Foo& ) = delete; // non copyable public: static Foo* create(); }