2010-01-29 13 views
11

Diciamo che ho questo programma:variabili statiche a metodi di istanza

class Foo { 
public: 
    unsigned int bar() { 
     static unsigned int counter = 0; 
     return counter++; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b; 
} 

(Naturalmente questo esempio non ha senso dato che avevo, ovviamente, dichiaro "contro" come attributo privato, ma è solo per illustrare il problema).

Mi piacerebbe sapere come si comporta C++ in questo tipo di situazione: la variabile "contatore" nel metodo bar() sarà la stessa per ogni istanza?

risposta

10

Sì, verrà condiviso tra tutte le istanze di oggetti di tipo nell'eseguibile. Finché ti trovi in ​​un ambiente singleton, funzionerà come previsto da un contatore condiviso.

In un ambiente con multithreading, si avranno condizioni di gara interessanti per eseguire il debug :).

+0

+1 per menzionare i pericoli in un ambiente con multithreading. – Omnifarious

+0

Supponendo che il compilatore non lo gestisca già per te. La definizione della lingua è che la variabile è consistente in tutte le chiamate al metodo. Quindi è compito del compilatore implemen- tarlo, quindi nei linguaggi multi-thread (prossima versione di C++) è il lavoro dei compilatori. In questa versione dipende dall'integrazione del compilatore con la libreria di threading. gcc ha già questo coperto e garanzie che l'accesso alla variabile statica è sicuro su più thread. –

+0

@ Martin York: vale a dire che le variabili statiche in C++ 0x sono garantite come thread locali? Che interessante, e forse potrebbe sorprendere molto alcune persone. Come un bel contatore di istanze di classi statiche. All'improvviso dovrai contare le istanze per thread. Non posso credere che farebbero un cambiamento del genere. Sei sicuro?! – Omnifarious

2

Per "essere lo stesso per ogni istanza" si intende che ci sarà un'istanza di questa variabile condivisa tra ogni istanza di classe, quindi sì, è corretto. Tutte le istanze della classe utilizzeranno la stessa istanza variabile.

Ma tieni presente che con le variabili di classe devi prendere in considerazione le cose come il multi-threading in molti casi, che è un argomento completamente diverso.

1

Da Il C++ Programming Language (2a edizione), pagina 200, da Bjarne Stroustrup:

Non utilizzare statica eccezione all'interno delle funzioni [semplici] (§7.1.2) e le classi (§10.2.4).

+4

Le regole sono fantastiche. __BUT__ solo se usato nel contesto corretto. Un utente nieve può prendere la citazione di hart. Se si è nominati per citare qualcosa del genere, si deve includere il contesto completo. –

0

Hai solo bisogno di capire due cose:

  1. variabili statiche vengono memorizzati in un'area statica del programma in esecuzione (che è uguale a quello della variabile globale).
  2. L'ambito è limitato dalle regole generali delle parentesi. Inoltre le variabili statiche hanno un collegamento interno.
+0

La durata della vita non è la vita del programma. È dal primo utilizzo (che potrebbe mai essere) fino alla distruzione (che è l'ordine inverso di creazione di variabili statiche). L'inizializzazione delle note di Alos è buona in quanto fa parte della funzione, non della classe. –

+0

@niel .. il mio male !! Non ho visto che – sud03r

+0

L'ultima frase riguarda le variabili statiche del namespace. Le variabili statiche locali (come quelle nella domanda) non hanno alcun collegamento. (Non c'è modo di riferirsi a variabili locali da diversi ambiti. Come faresti riferimento a una variabile definita in main? 'Main() :: v' non funziona, per esempio). –

1

Il vostro esempio è stato un paio di linee a partire da essere qualcosa che si potrebbe compilare e prova:

#include <iostream> 
using namespace std; 
class Foo { 
public: 
    unsigned int bar() { 
     static unsigned int counter = 0; 
     return counter++; 
    } 
}; 

int main() 
{ 
    Foo a; 
    Foo b; 

    for (int i=0; i < 10; i++) 
     cout<<i<<". "<<a.bar()<<"/"<<b.bar()<<endl; 
} 

L'output è simile al seguente:

0. 1/0 
1. 3/2 
2. 5/4 
3. 7/6 
4. 9/8 
5. 11/10 
6. 13/12 
7. 15/14 
8. 17/16 
9. 19/18 

Quindi sì, il contatore è condiviso in tutta tutte le istanze

+0

Ciò che è divertente è che l'output è un perfetto esempio di come i punti di sequenza e l'ordine di esecuzione funzionano e possono produrre risultati poco intuitivi. – Omnifarious

Problemi correlati