2015-04-21 10 views
16

Lo standard C++ richiede che l'inizializzazione dinamica di variabili statiche non locali sia eseguita nello stesso thread che chiama main()?Lo standard C++ richiede che l'inizializzazione dinamica delle variabili statiche sia eseguita nel thread principale?

Più specificamente, in C++ 11, è std::this_thread::get_id() garantito per restituire lo stesso risultato in inizializzatori statici e all'interno di main()?

Edit:

Ancora più specificamente, dato il codice seguente:

#include <iostream> 
#include <thread> 

static std::thread::id id = std::this_thread::get_id(); 

int main() 
{ 
     std::cout << id << "\n"; 
     std::cout << std::this_thread::get_id() << "\n"; 
     return 0; 
} 

sono i due ID filetto emessi necessari/garantiti per abbinare?

+8

inizializzazione statica ha una definizione molto specifico in C++: è zero inizializzazione e inizializzazione costante raggruppate insieme e non possono essere osservate da un programma. Quello che stai chiedendo è chiamato inizializzazione dinamica. – hvd

+0

Sembra che ci possa essere una domanda dietro questa domanda. Cosa stai cercando di realizzare? –

+0

No, è una domanda accademica (ispirata al comportamento del mondo reale osservato, ma in un contesto in qualche modo diverso). – Jeremy

risposta

0

Standard non dice nulla su quale thread deve eseguire tale inizializzazione. Si richiede solo ordinamenti e garanzie specifiche:

3.6.2 inizializzazione delle variabili non locali [basic.start.init]

2. inizializzazione statico deve essere eseguita prima di ogni inizializzazione dinamica prende posto. [...] Le variabili con inizializzazione ordinata definite all'interno di una singola unità di traduzione devono essere inizializzate nell'ordine delle loro definizioni nell'unità di traduzione. [...] Se un programma avvia una discussione, l'inizializzazione successiva di una variabile viene annullata rispetto all'inizializzazione di una variabile definita in una diversa unità di traduzione. Altrimenti, l'inizializzazione di una variabile è sequenzialmente indeterminata rispetto all'inizializzazione di una variabile definita in una diversa unità di traduzione.

4. È definito dall'implementazione se l'inizializzazione dinamica di una variabile non locale con durata di memorizzazione statica viene eseguita prima della prima istruzione di main.Se l'inizializzazione viene posticipata ad un certo punto nel tempo dopo la prima istruzione di main, deve avvenire prima del primo odr-uso di qualsiasi funzione o variabile definita nella stessa unità di traduzione della variabile da inizializzare.

5. È definito dall'implementazione se l'inizializzazione dinamica di una variabile non locale con durata di memorizzazione statica o di thread viene eseguita prima della prima istruzione della funzione iniziale del thread. Se l'inizializzazione viene posticipata ad un certo punto nel tempo dopo la prima istruzione della funzione iniziale del thread, deve avvenire prima del primo utilizzo odr di qualsiasi variabile con durata di memorizzazione del thread definita nella stessa unità di traduzione della variabile da inizializzare .

Tuttavia, la maggior parte delle implementazioni lo farà - l'inizializzazione delle variabili statiche non locali verrà eseguita nella stessa thread, che chiama main(). Esempio da Visual C++ 11:

#include <iostream> 
#include <thread> 

using namespace std; 

struct Cx 
{ 
public: 
    Cx() 
    { 
     cout<<"Cx: "<<std::this_thread::get_id()<<endl; 
    } 
}; 

static Cx c; 

int main() 
{ 
    cout<<"Main: "<<std::this_thread::get_id()<<endl; 
    return 0; 
} 

uscita:

Cx: 5820 
Main: 5820 

Dopo aver impostato breakpoint all'interno Cx::Cx():

enter image description here

+2

Provate a utilizzare effettivamente thread e più unità di traduzione. –

+0

Infatti, il codice postato illustra esattamente il caso che sto chiedendo. – Jeremy

+0

@ T.C. Cerca di capire la domanda e poi fai un downvote. Questa risposta è perfettamente valida per il caso che l'OP stava chiedendo. –

0

No, anche se potrebbe essere una buona idea scrivere il programma in questo modo. La sintassi richiede che l'inizializzazione statica avvenga in modo deterministico, ma non impone regole come il thread in questione.

+0

Se lo standard non lo garantisce, sicuramente non è una buona idea presumere che sia lo stesso thread. – Jeremy

+0

Ovviamente, volevo dire che spesso è una buona idea eseguire l'inizializzazione statica nel thread principale (principale). Ci può essere una situazione in cui ciò è impossibile e l'inizializzazione deve avvenire in un secondo momento (caricamento dinamico, lazy instantiation, ecc.) –

5

No. Lo standard fornisce nessuna tale garanzia, e in effetti il ​​contrario è implicito [basic.start.init]/p2:

Se un programma inizia una filettatura (30.3), la successiva inizializzazione di una variabile viene cancellata rispetto all'inizializzazione di una variabile definita in un'altra unità di traduzione. In caso contrario, l'inizializzazione di di una variabile viene sequenzialmente indeterminata rispetto a all'inizializzazione di una variabile definita in un'unità di conversione diversa . Se un programma avvia una discussione, la successiva inizializzazione non ordinata di una variabile viene annullata rispetto ad ogni altra inizializzazione dinamica . In caso contrario, l'inizializzazione non ordinata di una variabile viene sequenzialmente indeterminata rispetto ad ogni altra inizializzazione dinamica .

Non ci sarebbe bisogno di indebolire la garanzia di sequenziamento in presenza di thread se tutte le inizializzazioni dovevano essere eseguite sullo stesso thread.

+0

Il programma non sta iniziando alcun thread ed è tutto in una unità di traduzione. @Mateusz La risposta di Grzejek qui sotto illustra il caso e sembra citare le clausole più rilevanti. – Jeremy

+0

@Jeremy Dove appaiono queste qualifiche nella tua domanda? –

+0

Esempio di codice aggiunto. – Jeremy

Problemi correlati