Newsgroup: it.comp.lang.c++
Titolo: Singleton & statici

Costruire singleton con l'uso di static da la sicurezza che l'oggetto 
sia distrutto prima degli statici globali o il comportamento e' 
implementation defined?
Mi spiego meglio con un sorgente che su linux da questo risultato:
Costruisco statico 1
Costruisco statico 2
Entro in main.
Costruisco il singleton
Inizializzo singleton
Chiamata hello
Esco da main
Distruggo il singleton.
Distruggo statico 2
Distruggo statico 1
Posso aspettarmi che "singleton" sia sempre distrutto prima di "statico 
X"? Temo di no, ma volevo conferma :)
----
#include <iostream>
class Stat {
         int idx;
     public:
         Stat(int i) : idx(i) { std::cerr << "Costruisco statico " << 
idx << "\n"; }
         ~Stat() { std::cerr << "Distruggo statico " << idx << "\n"; }
};
Stat mystat1(1);
class Sing {
     public:
         static Sing &Instance() {
             static Sing sing;
             if (!sing.initted) {
                 std::cerr << "Inizializzo singleton\n";
                 sing.initted = true;
             }
             return sing;
         }
         void hello() { std::cerr << "Chiamata hello\n"; }
     private:
         Sing() : initted(false) { std::cerr << "Costruisco il 
singleton\n"; }
         ~Sing() { std::cerr << "Distruggo il singleton.\n"; }
         bool initted;
};
int main()
{
     std::cerr << "Entro in main.\n";
     Sing::Instance().hello();
     std::cerr << "Esco da main\n";
}
Stat mystat2(2);

implementation defined?
Temo che garanzie di questo tipo non siano offerte. A meno che non ci
sia un buon motivo per operare in ordine, l'ordine d'esecuzione non è
definito. Domanda: il pattern singleton è proprio brutto a mio parere,
perché vuoi usarlo? che stai realizzando?

 X"? Temo di no, ma volevo conferma :)
Questa garanzia ce l'hai solo se sia il singleton che gli statici sono
definiti nella stessa translation unit (corrispondente grosso modo
allo stesso file .cpp). In generale, se proprio devi utilizzare
variabili statiche, assicurati di usarle esclusivamente all'interno di
codice definito nello stesso file sorgente in cui sono definite.
Ciao,
Nicola

Domanda: il pattern singleton č proprio brutto a mio parere,
Perchč?
Con cosa lo rimpiazzeresti nei casi in cui tu debba definire un Manager 
di qualcosa, oppure un gestore di servizi (di cui esiste sempre una sola 
instanza), accessibile ovunque nel codice?
ciao

instanza), accessibile ovunque nel codice?
Scusa ma non puoi chiedermi con cosa rimpiazzerei un singleton se
avessi bisogno di un singleton. È quell'accessibile «ovunque» nel
codice che mi puzza. Un'alternativa che vedo è quella di passare
l'istanza del manager alle classi che ne necessitano.

 ciao
In casi del genere io utilizzo dei namespace al posto delle classi;
per esempio:
file: "manager.h"
namespace manager {
   extern int variabile;
   void metodo();
};
file: "manager.cpp"
namespace manager {
   int variabile;
   void metodo() { ..... };
}
Che ne dite, va bene come impostazione?

 }
Ti perdi la possibilita' che hai con un singleton di costruire l'oggetto 
runtime, solo e solo se e' necessario (chesso' x esempio un debugmanager 
o un profilemanager che non devono essere sempre abilitati ma solo se si 
lancia con certi flag), tra l'altro puoi anche gestire le eccezioni nel 
costruttore con un singleton, cosa che non puoi fare col tuo metodo 
(l'eccezione e' un abort perche' viene eseguita fuori dal main).
Nel caso specifico (qualcun altro lo aveva chiesto nel thread) i 
singleton vengono utilizzati x il configuration manager e x il logger, 
oggetti accessibili piu' o meno da tutti i vari moduli dell'applicazione.
Bye,
  Gabry

 lancia con certi flag) ...
Più che altro non mi piaceva il dover chiamare (col mio sistema) una
qualche:
Manager::init() e Manager::destroy()
Mentre col "singleton" costruzione e distruzione sono automatiche...

Mentre col "singleton" costruzione e distruzione sono automatiche...
Dal mio punto di vista, avere necessità di un "manager" di qualche
tipo significa restare ad un livello ancora troppo astratto di analisi
del problema. Un programma, in sé, è il manager di un problema;
costruire altri manager in seno ad esso significa solo rimandare il
problema a un "sottolivello", non scomporlo per la sua risoluzione.

 Costruisco il singleton
La soluzione per gestire l'ordine di creazione dei singleton sta nel
istanziare l'oggetto del singleton stesso alla prima necessità, quindi
con un oggetto creato nello heap:
class DynSingleton {
private:
	static DynSingleton *m_instance;
	DynSingleton();
	// ... eccetera
public:
	static DynSingleton *instance() {
		if (m_instance == 0)
			m_instance = new DynSingleton();
		return m_instance;
	}
};
In questo modo se diversi singleton dipendono gli uni dagli altri, e
quindi hanno un ordine logico di instanziazione, essa viene risolta
automaticamente... ovvero si è sempre certi che alla chiamata di
DynSyngleton::instance l'oggetto singleton esista già.
Riguardo i dubbi sull'uso dei singleton, concordo sul fatto che si
tratti di uno strumento importante e potente, di cui però è meglio non
abusare (come molti altri concetti, ereditarietà ed eccezioni in primis).
HTH
Federico Fuga