Perché alcune variabili const riferimento ad alcune variabili const esportate ottenere il valore 0?

StackOverflow https://stackoverflow.com/questions/920615

Domanda

Si consideri il seguente. Ho due costanti esportati come segue:

// somefile.h
extern const double cMyConstDouble;
extern const double cMyConstDouble2;

e

// somefile.cpp
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

Queste costanti sono ora riferimento qualche altro posto per definire due costanti statici (localmente visibili):

// someotherfile.cpp
#include "somefile.h"
static const double cAnotherDouble = 1.1*cMyConstDouble;
static const double cAnotherDouble2 = 1.1*cMyConstDouble2;
printf("cAnotherDouble = %g, cAnotherDouble2 = %g\n",
       cAnotherDouble, cAnotherDouble2);

che produce il seguente output:

cAnotherDouble = 3.454, cAnotherDouble2 = 0

Perché il doppio secondo 0? Sto utilizzando .NET 2003 compilatore C ++ (13.10.3077).

È stato utile?

Soluzione

A causa cMyConstDouble è dichiarata come extern, compilatore non è in grado di assumere il suo valore e non genera un tempo di compilazione di inizializzazione per cMyConstDouble2. Poiché non è compilare volta inizializzato il cMyConstDouble2, l'ordine di inizializzazione relative al cAnotherDouble2 è casuale (non definito). Vedere inizializzazione statico fiasco per più informazioni.

Altri suggerimenti

Non ho intenzione di immergere il dito del piede nelle questioni di extern qui, ma perché semplicemente non mettere i const nei file di intestazione appropriati e dimenticare "l'esportazione" utilizzando extern? Questo è il modo const dovrebbero essere utilizzati in C ++, e perché hanno il collegamento interno.

In altre parole:

// someheader.h
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

e # include il file che ovunque ne avete bisogno.

Questa è cosa pericolosa da fare come una variabile statica in un file sorgente dipende dalla un'altra variabile statica in un altro file cpp. Controllare statica di inizializzazione fiasco per ulteriori informazioni.

Se si modifica l'inizializzazione di cMyConstDouble2 a questo qui:

const double cMyConstDouble2 = 2.5*3.14;

Poi il programma dovrebbe comportarsi in modo corretto. La ragione di questo è che le variabili che

  • tipo hanno POD
  • vengono inizializzati con espressioni costanti (1)

vengono inizializzati in fase di inizializzazione statico. Questi includono inizializzazioni

  • Zero inizializzazione di tutti oggetti aventi durata di conservazione statica
  • Inizializzazioni dei baccelli inizializzate con espressioni costanti

le variabili indicate, solo soddisfa cMyConstDouble entrambe le condizioni di essere inizializzato completamente in fase di inizializzazione statico. Tuttavia, cMyConstDouble2 no, fin dalla sua inizializzatore non soddisfa i requisiti di un'espressione costante. In particolare, essa comprende una variabile che non dispone di tipo integrale (qui, è flottante punto). Tuttavia, in virgola mobile letterali sono ammessi in aritmetiche espressioni costanti. Questo è il motivo 2.5*3.14 è un'espressione costante aritmetica. Ed è per questo cambiare l'inizializzatore a che richiederà di essere inizializzato in modo statico.


Che cosa accadrà con cMyConstDouble2 se si rimane con l'espressione non costante? La risposta è, non si sa. Lo Standard permette tale variabile da inizializzare staticamente, ma non richiede di farlo. Nel tuo caso, è stato inizializzato in modo dinamico - così il suo valore solo dopo il tempo di inizializzazione statico era ancora pari a zero. Per ottenere una sensazione di come complicato che è, ecco un esempio:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
                // may be statically initialized to 0.0 or
                // dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0

Se l'inizializzazione dinamica non cambia qualsiasi altra variabile di archiviazione statica (soddisfatte in tuo codice) e quando l'inizializzazione statica produrrebbe lo stesso valore come sarebbe prodotto da inizializzazione dinamica quando tutti non oggetti necessario per essere inizializzato in modo statico sarebbe stato inizializzato in modo dinamico (anche soddisfatto in tuo codice) - allora la variabile è permesso di essere inizializzato in modo statico. Queste due condizioni sono soddisfatte anche nel codice qui sopra per entrambe le variabili d2 e d1:

L'analisi dei d2

  • = d1 non cambia qualsiasi altra variabile di memorizzazione static
  • Quando sia d2 e d1 vengono inizializzati dinamicamente, quindi d2 sarebbe inizializzato a 0.0, perché d2 viene definito prima d1, e l'inizializzazione dinamica di d2 sarebbe afferrare il valore di d1 come dello stato appena dopo inizializzazione statico (dove zero solo inizializzazione del d1 ha avuto luogo).

L'analisi dei d1

  • = fd() non cambia qualsiasi altra variabile di memorizzazione static
  • Quando sia d2 e d1 vengono inizializzati in modo dinamico, quindi = fd() inizializza d1 a 1.0.

Quindi, il compilatore può inizializzare d1 staticamente a 1.0, perché sono soddisfatte entrambe le condizioni per facoltativo-static-inizializzazione.

  • Se il compilatore decide per inizializzare d1 e d2 modo dinamico, quindi d2 verrà inizializzato per 0.0 , dal momento che afferrare il valore di d1 come era subito dopo l'inizializzazione a zero.

  • Tuttavia , se il compilatore decide per inizializzare d1 staticamente e d2 dinamico, quindi verrà inizializzato d2 a 1.0 , in quanto l'inizializzazione dinamica di d2 sarà afferrare il valore dell'inizializzazione del d1 come è stato appena dopo initializatio staticon.

Non sono sicuro di quale sia il valore di d2 è quando d1 e d2 viene inizializzato in modo statico, però. Cioè, se d2 dovrebbe afferrare il 0.0 o 1.0, dal momento che non esiste un ordine definito per l'inizializzazione statica.


(1) espressioni costanti includono aritmetiche espressioni costanti troppo (non solo integrali espressioni costanti), quando si considera ordine di inizializzazione di oggetti con durata di conservazione statica.

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