Domanda

Sono abituato a pensare a tutto l'inizializzazione di variabili globali / static-classe-utenti come accade prima della prima riga di main (). Ma di recente ho letto da qualche parte che lo standard permette di inizializzazione accada in seguito a "assistere con caricamento dinamico di moduli." Ho potuto vedere questo essere vero quando il collegamento dinamico: non mi aspetto un globale inizializzato in una libreria da inizializzare prima dlopen'ed biblioteca. Tuttavia, all'interno di un raggruppamento di collegate staticamente insieme unità di traduzione (file .o diretti di mia app) avrei trovato questo comportamento molto poco intuitivo. Questo accade solo quando pigramente in modo dinamico il collegamento o può accadere in qualsiasi momento? (O era quello che ho letto solo sbagliato;?)

È stato utile?

Soluzione

Lo standard è la seguente in 3.6.2 / 3:

  

Si attuazione definita o meno l'inizializzazione dinamica (8.5, 9.4, 12.1, 12.6.1) di un oggetto di   ambito dello spazio dei nomi viene fatta prima della prima istruzione del principale. Se l'inizializzazione viene differita a un certo punto   nel tempo dopo la prima istruzione del principale, deve avvenire prima del primo uso di una funzione o oggetto definito   nella stessa unità di conversione come oggetto da inizializzare.

Ma o Naturalmente è possibile mai ufficialmente dire quando l'inizializzazione avviene poiché l'inizializzazione avverrà prima di accedere alla variabile! come segue:

// t1.cc
#include <iostream>
int i1 = 0;

int main () {
  std::cout << i1 << std::endl

// t2.cc
extern int i1;
int i2 = ++i1;

Posso essere conforme che g ++ 4.2.4 almeno sembra per eseguire l'inizializzazione di 'i2' prima principale.

Altri suggerimenti

Il problema che si voleva risolvere con quella regola è quella di caricamento dinamico. L'indennità non è limitata ai carichi dinamici e formalmente potrebbe accadere per gli altri casi. Non so un'implementazione che utilizzano per altro che il caricamento dinamico.

Rivediamo un pseudocodice:

In DLL:

static int ItsDllVar = 1;
int EXPORTED_FUNCTION() { return ItsDllVar; }

In applicazione:

static int AppVar1 = 2;
static int AppVar2 = EXPORTED_FUNCTION() + AppVar1;

Quindi, secondo statica inizializzazione AppVar2 prende 1 + 2 = 3

Pigro inizializzazione applicabile per le variabili statiche locali (indipendentemente DLL)

int f()
{
    static int local_i = 5;//it get's 5 only after visiting f()
    return local_i;
}

Credo che questo sia quello che è successo nel mio caso con g ++ 4.7 e CMake (non so se questo è un dettaglio rilevante per quanto riguarda CMake). Ho un codice che registra una funzione in fabbrica. Essa si basa sul costruttore chiamare da una variabile inizializzata a livello globale.

Quando questo codice era in libreria collegata staticamente l'inizializzazione non è accaduto! Si sta lavorando bene, quando mi sono trasferito ai file oggetto che collegavano direttamente (vale a dire, non sono combinati in una libreria di prima).

Quindi, ho il sospetto che lei ha ragione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top