2011-01-28 23 views
27
class MyClass 
{ 
    int x, y; 
    void foo() volatile { 
     // do stuff with x 
     // do stuff with y 
    } 
}; 

Devo dichiarare "x" e "y" come volatili o tutte le variabili membro vengono considerate automaticamente come volatili?Funzioni membro volatile C++

Voglio assicurarmi che "roba con 'x'" non sia riordinato con "cose ​​con 'y'" dal compilatore.

MODIFICA: Cosa succede se sto trasmettendo un tipo normale a un tipo volatile? Questo dovrebbe istruire il compilatore a non riordinare l'accesso a quella posizione? Voglio passare una variabile normale in una situazione speciale a una funzione il cui parametro è volatile. Devo essere sicuro che il compilatore non riordini quella chiamata con letture e scritture precedenti o successive.

+2

grande domanda. –

+0

http: // stackoverflow correlato.it/questions/2444734/what-is-the-purpose-of-un-membro-volatile-function-in-c –

risposta

22

Contrassegnare una funzione membro volatile è come contrassegnarlo const; significa che l'oggetto destinatario viene trattato come se fosse dichiarato come volatile T*. Di conseguenza, qualsiasi riferimento a x o verrà considerato come un valore volatile letto nella funzione membro. Inoltre, un oggetto volatile può solo chiamare le funzioni membro volatile.

Detto questo, si consiglia di segnare x e yvolatile in ogni caso, se davvero si vuole tutti gli accessi a loro di essere trattati come volatile.

4

Il seguente codice:

#include <iostream> 

class Bar 
{ 
    public: 

     void test(); 
}; 

class Foo 
{ 
    public: 

     void test() volatile { x.test(); } 

    private: 

     Bar x; 
}; 

int main() 
{ 
    Foo foo; 

    foo.test(); 

    return 0; 
} 

genera un errore al momento di compilazione con gcc:

main.cpp: In member function 'void Foo::test() volatile': 
main.cpp:14:33: error: no matching function for call to 'Bar::test() volatile' 
main.cpp:7:8: note: candidate is: void Bar::test() <near match> 

E poiché un'istanza volatile non può chiamare un metodo non-volatile, si può supporre che, sì, x e saranno volatile nel metodo, anche se l'istanza di MyClass non viene dichiarata volatile.

Nota: è possibile rimuovere il qualificatore volatile utilizzando un const_cast<> se è necessario; tuttavia, fai attenzione perché, come in questo caso, const può comportare un comportamento indefinito in alcuni casi.

+0

Correggimi se ho torto su questo, ma non sono la semantica delle funzioni volatili come quella di const funziona in quanto è possibile chiamare una funzione volatile su un oggetto non volatile, ma non una funzione non volatile da un oggetto volatile? – templatetypedef

+0

@ ereOn- Un test rapido in 'g ++' suggerisce che si possano effettivamente chiamare le funzioni membro 'volatile' da oggetti on-'volatili'. La ragione per cui 'volatile std :: string's è inutile è perché se la stringa stessa è' volatile', può solo chiamare le funzioni membro 'volatile', di cui non ce ne sono. $ 4.4.1 dello standard chiarisce che è possibile convertire implicitamente un T * in T * volatile, e $ 9.3.1.3 dice che il qualificatore 'volatile' influenza il puntatore' this', suggerendo che se si ha un oggetto di tipo 'T ', il puntatore' this' di tipo 'T *' potrebbe essere convertito in un 'T * volatile 'per la chiamata. – templatetypedef

+0

@templatetypedef: ho invertito la logica (sono solo le 7:00, ho ancora bisogno di dormire;)). Grazie, ora è riparato. È possibile chiamare un metodo 'volatile' da un'istanza' volatile' e 'non-volatile'. Ma se la tua istanza è 'volatile' non sarai in grado di chiamare i metodi' non-volatile'. – ereOn

6

È Non devono dichiarare le variabili membro esplicitamente ..

Da documenti standard 9.3.2.3,

Allo stesso modo, la semantica volatili (7.1.6.1) applicare in funzioni membro volatile quando si accede all'oggetto e ai suoi membri dati non statici .

1

Quindi, utilizzando l'esempio originale:

class MyClass 
{ 
    int x, y; 
    void foo() volatile { 
     // do stuff with x 
     // do stuff with y 
     // with no "non-volatile" optimization of the stuff done with x, y (or anything else) 
    } 
    void foo() { 
     // do stuff with x 
     // do stuff with y 
     // the stuff done with x, y (and anything else) may be optimized 
    } 
}; 
Problemi correlati