sobrecarga por poo objetos destructores defecto copia constructores c++ idioms raii

c++ - por - destructores poo



Buenas o malas expresiones idiomáticas de C++: ¿objetos usados ​​puramente para constructor/destructor? (9)

Tengo algunas clases que no hacen nada excepto en sus constructores / destructores. Aquí hay un ejemplo

class BusyCursor { private: Cursor oldCursor_; public: BusyCursor() { oldCursor_ = CurrentCursor(); SetCursor(BUSY_CURSOR); } ~BusyCursor() { SetCursor(oldCursor_); } } // example of use void DoSlowThing { BusyCursor busy; ... do something time-consuming ... }

Estoy un poco preocupado por la legibilidad futura. ¿Estoy siendo demasiado "truculento" aquí, con una variable ("ocupado") que nunca se usa realmente en el código? ¿Podría alguna herramienta de análisis estático sugerir que se eliminen, o es este lenguaje lo suficientemente común como para no preocuparse?


Como otros han dicho, este es un buen estilo de C ++. Para ayudar a la legibilidad, siempre prefijo tales clases exclusivas de RAII con Scoped (por ejemplo, ScopedBusyCursor ) para dejar en claro de un vistazo cuál es el propósito de la clase.


Es un buen idioma y de uso común.

Es mejor que cualquier alternativa, por ejemplo, incluso si su código que consume mucho tiempo arroja una excepción, el ~BusyCursor destructor seguirá siendo llamado.


Esta es una expresión idiomática de C ++ bien conocida y buena, como las otras respondieron.

Para dejar en claro que las clases están destinadas a ser utilizadas únicamente dentro de un alcance y no para ser movidas entre diferentes ámbitos, podría ser bueno hacer que no se puedan copiar. Esto se puede hacer de forma manual al agregar un operador privado de copia-constructor y un operador de asignación de copia sin implementar. La forma más corta y más legible es derivar la clase de boost :: noncopyable :

#include <boost/noncopyable.hpp> class BusyCursor : public boost::noncopyable // for scoped use only { // ... };


Esta técnica es muy común y se conoce como el patrón de diseño: la adquisición de recursos es la inicialización (RAII) .

No dudaría en usar este patrón de diseño en absoluto.

Es mucho mejor que esté codificando utilizando este patrón de diseño porque evitará errores al olvidar reiniciar el cursor, o cualquiera que sea el recurso en cuestión.

Si le preocupa que otros programadores puedan no entenderlo, entonces esos programadores deberían ser más educados. Siempre trata de codificar de la manera más libre de errores en la que haces imposible que tú y los demás te disparen en el pie.

"¿Podría alguna herramienta de análisis estático sugerir que se eliminen?"

  • Ninguna herramienta de análisis estático verá esto como un problema.
  • No se dará ninguna advertencia del compilador
  • Ninguna optimización del compilador causará ningún problema.

La razón es porque el objeto se crea y se llama al constructor / destructor. Entonces no es una variable sin referencia.


Ninguna herramienta sensata de análisis estático sugiere eliminar la variable, porque se usa. Tiene un efecto porque se llama a su constructor y destructor. Deberías estar perfectamente seguro.


Podría decirse que no usar este patrón es la mala expresión. Cuando no estás usando RAII, tu código termina luciendo así:

void func() { Cursor oldCursor = CurrentCursor(); SetCursor(BUSY_CURSOR); try { do_slow_stuff(); SetCursor(oldCursor); } catch (...) { SetCursor(oldCursor); throw; } }

¿De verdad crees que tener todo eso ensuciado en tu código es mejor para el mantenimiento?


Usualmente me refiero a esto como un "guardia". En mi opinión, demuestra una de las mayores fortalezas de C ++ (manejo determinista de recursos). Es una de las cosas que más extraño cuando trabajo en lenguajes recolectados con basura.


También puede elegir algo como ScopeGuard de Andrei Alexandrescu y Petru Marginean. Su muestra se vería así:

void DoSlowThing { Cursor oldCursor = CurrentCursor(); SetCursor(BUSY_CURSOR); ON_BLOCK_EXIT(SetCursor, oldCursor); ... do something time-consuming ... }

Esto hace que sea más fácil realizar operaciones únicas de tipo RAII sin tener que crear una nueva clase para cada una. Sin embargo, para su ejemplo de Cursor, dado que es una clase que probablemente reutilizará muchas veces, probablemente esté mejor con la clase dedicada.


Otros ya han mencionado que esto es clásico RAII. Lo que añadiré es decir que esta es una de las mejores cosas sobre C ++. Muy pocos otros lenguajes lo soportan, o al menos lo soportan apropiadamente (incluso el uso de construcción de C # no es tan bueno, ya que la carga todavía está en el código del cliente - vea la entrada de mi blog sobre esto ).

Se ha asociado tan estrechamente con C ++ que debes tener la seguridad de que cualquiera que lo lea estará familiarizado con él, y si no, debería estarlo.