pattern c++ design-patterns singleton

pattern - ¿Alguien puede proporcionarme una muestra de Singleton en c++?



singleton pattern c# (9)

¿Por qué todos quieren devolver un singleton como puntero?
¡Devolverlo como referencia parece mucho más lógico!

Nunca deberías poder liberar un singleton manualmente. ¿Cómo sabes quién está manteniendo una referencia al singleton? Si no sabe (o no puede garantizar) que nadie tiene una referencia (en su caso mediante un puntero), entonces no tiene ningún motivo para liberar el objeto.

Usa la estática en un método de función.
Esto garantiza que se crea y destruye solo una vez. También le da inicialización perezosa de forma gratuita.

class S { public: static S& getInstance() { static S instance; return instance; } private: S() {} S(S const&); // Don''t Implement. void operator=(S const&); // Don''t implement };

Tenga en cuenta que también necesita hacer que el constructor sea privado. También asegúrese de anular el constructor de copia y el operador de asignación predeterminados para que no pueda hacer una copia del singleton (de lo contrario, no sería un singleton).

Lea también:

Para asegurarse de que está utilizando un singleton por las razones correctas.

Aunque técnicamente no es seguro para subprocesos en el caso general, consulte:
¿Cuál es el tiempo de vida de una variable estática en una función de C ++?

GCC tiene un parche explícito para compensar esto:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg00265.html

Escribo un singleton c ++ de la siguiente manera:

class A { private: static A* m_pA; A(); virtual ~A(); public: static A* GetInstance(); static void FreeInstance(); void WORK1(); void WORK2(); void WORK3(); } } A* A::GetInstance() { if (m_pA == NULL) m_pA = new A(); return m_pA; } A::~A() { FreeInstance() // Can I write this? are there any potential error? } void A::FreeInstance() { delete m_pA; m_pA = NULL; }

¡Gracias! La respuesta de Evan Terán y sep61.myopenid.com es correcta, ¡y realmente buena! Mi camino está equivocado, deseo que cualquiera que escriba ese código pueda evitar mi tonto error.

Mi singleton A en mi proyecto tiene un vector de puntero inteligente, y otro hilo también puede editar este vector, por lo que cuando la aplicación se está cerrando, siempre se vuelve inestable, incluso agrego montones de CMutex. Error de secuencia múltiple + error singleton me desperdició 1 día.

// ------------------------------------------------ ----------- Un singleton nuevo, le invitamos a editar si cree que hay algún problema en la siguiente muestra:

class A { private: static A* m_pA; explicit A(); void A(const A& a); void A(A &a); const A& operator=(const A& a); virtual ~A(); public: static A* GetInstance(); static void FreeInstance(); void WORK1(); void WORK2(); void WORK3(); } } A* A::GetInstance() { if (m_pA == NULL){ static A self; m_pA = &self; } return m_pA; } A::~A() { }


Después de un período de gran entusiasmo por los singletons de estilo Meyers (utilizando objetos estáticos locales como en algunas de las respuestas anteriores), me cansé por completo de los problemas de administración de por vida en aplicaciones complicadas.

Tiendo a encontrar que terminas haciendo referencia al método de ''Instancia'' deliberadamente al principio de la inicialización de la aplicación, para asegurarte de que se crean cuando lo deseas, y luego jugar todo tipo de juegos con el derribo debido a lo impredecible (o al menos muy complicado y algo oculto) orden en el que las cosas se destruyen.

YMMV, por supuesto, y depende un poco de la naturaleza del singleton en sí, pero una gran cantidad de waffle sobre singleton inteligentes (y los problemas de enhebrado / bloqueo que rodean la astucia) está sobrevalorado OMI.


Esta implementación está bien siempre que pueda responder estas preguntas:

  1. ¿Sabes cuándo se creará el objeto (si usas un objeto estático en lugar de uno nuevo? ¿Tienes un main ()?)

  2. ¿tiene alguna dependencia que no esté lista para el momento en que se creó? Si usa un objeto estático en lugar de nuevo, ¿qué bibliotecas se han inicializado en este momento? ¿Qué hace tu objeto en el constructor que pueda necesitarlos?

  3. ¿Cuándo se eliminará?

Usar new () es más seguro porque usted controla dónde y cuándo se creará y eliminará el objeto. Pero luego debe eliminarlo explícitamente y probablemente nadie en el sistema sepa cuándo hacerlo. Puedes usar atexit () para eso, si tiene sentido.

Usar un objeto estático en el método significa que realmente no se sabe cuándo se creará o eliminará. También podría usar un objeto estático global en un espacio de nombres y evitar getInstance () en absoluto, no agrega mucho.

Si usas hilos, entonces estás en un gran problema. Es virtualmente imposible crear singleton seguro de hilos utilizables en C ++ debido a:

  1. bloqueo permanente en getInstance es muy pesado - un cambio de contexto completo en cada getInstance ()
  2. el bloqueo verificado doble falla debido a las optimizaciones del compilador y al modelo de memoria débil / caché, es muy difícil de implementar e imposible de probar. No trataría de hacerlo en un sistema real, a menos que conozca íntimamente su arquitectura y quiera que no sea portátil

Estos se pueden buscar en Google fácilmente, pero aquí hay un buen enlace en el modelo de memoria débil: http://ridiculousfish.com/blog/archives/2007/02/17/barrier .

Una solución sería usar el bloqueo pero requiere que los usuarios guarden en caché el puntero que obtienen de getInctance () y estén preparados para que getInstance () sea pesado.

Otra solución sería permitir que los usuarios manejen ellos mismos la seguridad de los hilos.

Otra solución más sería usar una función con bloqueo simple y sustituirla por otra función sin bloqueo y comprobación una vez que se haya llamado al nuevo (). Esto funciona, pero la implementación total es complicada.



No creo que haya ninguna razón para escribir esa línea no. Su método destructor no es estático y su instancia singleton no será destruida de esa manera. No creo que el destructor sea necesario; si necesita limpiar el objeto, use el método estático que ya ha creado, FreeInstance ().

Aparte de eso, creas tus singletons más o menos de la misma manera que yo creo los míos.


No olvides hacer que el constructor de copias y los operadores de asignaciones sean privados.


Puede evitar tener que eliminarlo utilizando un objeto estático como este:

if(m_pA == 0) { static A static_instance; m_pA = &static_instance; }


Si lees "Modern C ++ Design", te darás cuenta de que un diseño singleton podría ser mucho más complejo que devolver una variable estática.


Un singleton en C ++ se puede escribir de esta manera:

static A* A::GetInstance() { static A sin; return &sin; }