2011-07-07 8 views
7

Me parece que hacer una clase no copiable me ayuda mucho con la calidad de mi código. Inicialmente, hice esto con boost :: noncopyable, pero encontré que los errores del compilador de VC++ no eran tan útiles como con los miembros privados (haciendo doble clic en el lugar equivocado en el código).C++ No se puede copiar, excepto a veces

T(T const&); 
T& operator=(T const&); 

De hecho, me ha alertado de bastantes casos donde las clases no se pasaron como referencia donde deberían tener. Tanto es así, que me gustaría recibir una advertencia incluso en las clases que solo necesito copiar una vez.

¿Hay una buena manera de hacerlo? Estaba pensando, por ejemplo, en dejar por encima dos métodos privados y agregar un constructor público T (T const &, bool dummy) para llamar cuando realmente quiero copiar constructo. O, alternativamente, puede hacer que los dos métodos anteriores sean públicos y, de alguna manera, activar una advertencia del compilador cuando copie la construcción, suprimiendo la advertencia donde yo quiera.

¿O tal vez hay una mejor manera en conjunto?

Respuesta

6

No estoy seguro de si es exactamente lo que quiere, pero si marca el constructor de copia explicit, la clase no se puede pasar por valor o inicializar copia, pero puede copiar-construir mediante inicialización directa.

Es de suponer que desea mantener el operador de asignación privado, tal vez una base NonAssignable sería útil para eso.

+1

Me gusta esta respuesta mejor. El problema con los constructores de copias, en mi experiencia, es cuando se invocan "por accidente" en un objeto enorme. 'explicit' te obliga a pensar al invocarlos, lo cual debería ser suficiente. – Nemo

+0

Saludos, esto se adapta perfectamente a mis necesidades. Gracias. – Cookie

2

Creo que nombró una manera perfecta allí mismo.

acabo de recordar un pequeño truco aseado Una vez jugué en otra base de código que trabajé en (?):

struct T 
{ 
    friend class SomeClientThatCanConstructT; 
    T(T const&); 

    private: 
    T(T const&);   
}; 

Como se ha discutido en los comentarios la siguiente no va a volar

Puede optar por un nombre explícito (como CopyConstruct) y confiar en que RVO sea igualmente eficiente:

struct T 
{ 
    inline T CopyConstruct() const  { return *this; } 
    inline T& AssignTo(T& dst) const { return dst = *this; } 
    inline T& AssignFrom(const T& src) { return *this = src; } 

    private: 
    T(T const&); 
    T& operator=(T const&); 
}; 

+0

Pensé en esto pero su 'CopyConstruct' requiere que el constructor de copia sea accesible incluso si el compilador no lo llama. –

+0

Shute. Gracias por recordarme. Esto es de hecho un tapón. Por supuesto, puede uglificarlo todo el tiempo, pero para la llamada de constructor, realmente no hay alternativa a su solución de 'parámetro de etiqueta'. Ahora que lo pienso, de repente recuerdo haber hecho esto yo mismo ...Actualizando la respuesta – sehe

+0

Ese bit de amigo parece hacer el truco ahora. –

0

Usted podría construir un defecto T y luego añadir un método assign de usar. Sin embargo, esto no parece totalmente óptimo, lo que indica que es posible que desee revisar sus necesidades de copia.

0

No me gusta la idea de restringir un tipo (CopyConstructible es un concepto muy utilizado en todo el stdlib) porque podría ser mal utilizado. Si puede construir un objeto desde otra instancia, debe ser copiable. También distrae al lector del código importante sin servir a ningún propósito real.

Tal vez una advertencia o aserción en modo de depuración que se activa por el constructor de copia es realmente lo que estás buscando?

+0

¿Existe tal cosa? p.ej. ¿Podría definir una advertencia definida por el usuario siempre que el compilador o el enlazador se vincule a una función? y luego suprimir la advertencia en el archivo objeto que quiero? Como una advertencia pragma desactivar? – Cookie

Cuestiones relacionadas