c++ how Quali sono le regole per l'inizializzazione della statica non locale?



vector c++ 98 (2)

Supponiamo che io abbia una classe il cui unico scopo sono gli effetti collaterali causati durante la costruzione dei suoi oggetti (ad esempio, registrando una classe con una fabbrica):

class SideEffectCauser {
public:
  SideEffectCauser() { /* code causing side-effects */ }
};

Supponiamo anche che mi piacerebbe avere un oggetto per creare tali effetti collaterali una volta per ciascuna delle diverse unità di traduzione. Per ciascuna di tali unità di traduzione, mi piacerebbe essere in grado di inserire un oggetto SideEffectCauser nello scope dei nomi nel file .cpp, ad es.

SideEffectCauser dummyGlobal;

ma 3.6.2 / 3 dello standard C ++ 03 suggerisce che questo oggetto non sia necessariamente costruito a meno che non venga usato un oggetto o una funzione nel file .cpp, e articoli come this e discussioni online come this suggeriscono che tale gli oggetti a volte non sono inizializzati.

D'altra parte, esiste un modo per creare un'istanza di oggetti da una stringa che contiene il loro nome di classe? ha una soluzione che si dice funzioni, e noto che si basa sull'utilizzo di un oggetto di un tipo come SideEffectCauser come membro statico dei dati, non come globale, ad es.

class Holder {
  static SideEffectHolder dummyInClass;
};

SideEffectHolder Holder::dummyInClass;

Sia dummyGlobal che dummyInClass sono dummyInClass non locali, ma uno sguardo più ravvicinato al 3.6.2 / 3 dello standard C ++ 03 mostra che quel passaggio si applica solo agli oggetti nello scope namespace. Non riesco a trovare nulla nello standard C ++ 03 che dice quando le statiche non locali nell'ambito della classe sono inizializzate dinamicamente, sebbene 9.4.2 / 7 suggerisca che le stesse regole si applichino a loro come a statiche non locali nello spazio dei nomi scopo.

Domanda 1: In C ++ 03, c'è qualche ragione per credere che dummyInClass abbia più probabilità di essere inizializzato di dummyGlobal ? O possono entrambi andare non inizializzati se non vengono utilizzate funzioni o oggetti nella stessa unità di traduzione?

Domanda 2: Qualcosa cambia in C ++ 11? La formulazione in 3.6.2 e 9.4.2 non è la stessa delle versioni di C ++ 03, ma, da quello che posso dire, non c'è alcuna differenza comportamentale specificata per gli scenari che descrivo sopra.

Domanda 3: Esiste un modo affidabile per utilizzare oggetti di una classe come SideEffectHolder al di fuori di un corpo di una funzione per forzare l' SideEffectHolder di effetti collaterali?


Answer #1

Penso che l'unica soluzione affidabile sia progettare questo per specifici compilatori e runtime. Nessuno standard copre l'inizializzazione di globals in una libreria condivisa che ritengo sia il caso più complesso, in quanto dipende molto dal caricatore e quindi dipende dal sistema operativo.

Q1: No Q2: non in senso pratico Q3: non in un modo standard


Answer #2

Sto usando qualcosa di simile con g ++ / C ++ 11 sotto Linux e ottenere le mie fabbriche registrate come previsto. Non sono sicuro del motivo per cui non avresti richiamato le funzioni. Se ciò che descrivi deve essere implementato, significa che ogni singola funzione in quell'unità deve chiamare la funzione di inizializzazione. Non sono troppo sicuro di come si possa fare. Le mie fabbriche si trovano anche all'interno degli spazi dei nomi, sebbene siano denominate spazi dei nomi. Ma non vedo perché non si chiamerebbe.

namespace snap {
namespace plugin_name {
class plugin_name_factory {
public:
  plugin_name_factory() { plugin_register(this, name); }
...
} g_plugin_name_factory;
}
}

Nota che la parola chiave static non dovrebbe essere più utilizzata in C ++. Spesso è più lento avere una definizione statica di una globale.





c++11