c++ - ejemplo - singleton linux
Destructor para campos estáticos. Realización singleton (3)
Entonces, la simple realización clásica de Singleton es la siguiente:
class Singleton
{
private:
static Singleton* singleton;
Singleton() {}
public:
static Singleton* getInstance();
};
cpp-file :
Singleton* Singleton::singleton = 0;
Singleton* Singleton::getInstance()
{
if (!singleton)
{
singleton = new Singleton;
}
return singleton;
}
Veo fuga de memoria aquí, porque no hay eliminación para el nuevo . Pero en C ++ no hay destructor estático, ¿entonces no nos importa esta fuga de memoria?
Por qué debería evitar dicho código, cuando no hay una delete
correspondiente para el new
Si bien no existe una pérdida de memoria real (en la mayoría de los sistemas operativos modernos), lo peor es que su destructor Singleton
no se llama. Y si adquiere algunos recursos, probablemente se filtrarían.
Qué se puede hacer aquí
Utilice el puntero inteligente para almacenar la instancia, considere std::unique_ptr
(con C ++ 11) o boost::auto_ptr
Cuando una variable local para una función se declara "estática", significa que no está asignada en la pila, y que su valor persiste de una llamada a la siguiente.
Una pérdida de memoria es más que una asignación sin coincidencia gratuita. Es cuando tienes memoria que se puede recuperar porque el objeto ya no se usa, pero que en realidad nunca se libera. De hecho, muchas pérdidas de memoria son casos donde hay un código en el programa para desasignar la memoria, pero por cualquier razón no se llama (por ejemplo, un ciclo de referencia). De hecho, hay mucha investigación sobre cómo detectar este tipo de fugas; este documento es un excelente ejemplo de una de esas herramientas.
En el caso de un singleton, no tenemos una fuga porque ese singleton existe en todo el programa. Su vida útil nunca está destinada a terminar, por lo que la memoria no recuperada no es un problema.
Dicho esto, el código que tienes arriba no es cómo la mayoría de la gente implementaría un singleton. La implementación canónica de C ++ sería algo como esto:
class Singleton
{
private:
/* No instantiation. */
Singleton() {}
/* Explicitly disallow copying. */
Singleton(const Singleton&) = delete;
Singleton& operator= (const Singleton&) = delete;
/* In C++03, the above would be written as
*
* Singleton(const Singleton&);
* Singleton& operator= (const Singleton&);
*
* and you''d just leave the methods unimplemented.
*/
public:
static Singleton& getInstance();
};
archivo .cpp:
Singleton& Singleton::getInstance() {
/* Have a static local variable representing the unique instance. Since
* it''s static, there is only one instance of this variable. It''s also only
* initialized when getInstance is called.
*/
static Singleton theInstance;
return theInstance;
}
Ahora no hay ninguna asignación dinámica en absoluto: la memoria es asignada por el compilador y probablemente reside en el código o segmento de datos en lugar de en el montón. También tenga en cuenta que tiene que rechazar explícitamente la copia, o de lo contrario podría terminar con muchos clones del singleton.
La otra ventaja de esto es que C ++ garantiza que al salir del programa (suponiendo que el programa termina normalmente), el destructor de theInstance
se theInstance
al final del programa. Así puede definir un destructor con todo el código de limpieza que necesita.
¡Espero que esto ayude!