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

¿Debo declarar 'x' e 'y' como volátil o todas las variables miembro se tratarán como volátiles automáticamente?C++ funciones de miembro volátil

Quiero asegurarme de que "cosas con 'x'" no se reordenen con "cosas con 'y'" por el compilador.

EDITAR: ¿Qué sucede si estoy convirtiendo un tipo normal en uno volátil? ¿Esto instruiría al compilador a no reordenar el acceso a esa ubicación? Quiero pasar una variable normal en una situación especial a una función cuyo parámetro es volátil. Debo estar seguro de que el compilador no reordena esa llamada con lecturas y escrituras anteriores o seguidas.

+2

Muy buena pregunta. –

+0

relacionado http: // stackoverflow.com/questions/2444734/what-is-the-purpose-of-a-volatile-member-function-in-c –

Respuesta

22

Marcar una función de miembro volatile es como marcarlo const; significa que el objeto receptor se trata como si se hubiera declarado como volatile T*. Consecuentemente, cualquier referencia a x o y será tratada como volatile leída en la función de miembro. Además, un objeto volatile solo puede llamar a las funciones de miembro volatile.

Dicho esto, es posible que desee marcar y xyvolatile de todos modos si usted realmente quiere todos los accesos a ellas para ser tratado como volatile.

4

El siguiente código:

#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; 
} 

Eleva un error en la compilación 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> 

Y como una instancia volatile no puede llamar a un método non-volatile, podemos suponer que, sí, x y y serán volatile en el método, incluso si la instancia de MyClass no está declarada volatile.

Nota: puede eliminar el calificador volatile usando const_cast<> si alguna vez lo necesita; sin embargo, tenga cuidado porque al igual que const hacerlo puede provocar un comportamiento indefinido en algunos casos.

+0

Corrígeme si me equivoco sobre esto, pero no es la semántica de funciones volátiles como la de const funciones en que puede llamar a una función volátil en un objeto no volátil, pero no una función no volátil de un objeto volátil? – templatetypedef

+0

@ ereOn- Una prueba rápida en 'g ++' sugiere que usted puede llamar a funciones de miembros 'volátiles' desde objetos' 'volátiles ''. La razón por la que 'volatile std :: string's es inútil es porque si la cadena en sí es 'volátil', solo puede llamar a las funciones miembro' volátiles', de las cuales no hay ninguna. $ 4.4.1 de la norma aclara que puede convertir una T * a una T * volátil implícitamente, y $ 9.3.1.3 dice que el calificador 'volátil 'afecta al puntero' this', lo que sugiere que si tiene un objeto de tipo 'T ', el puntero' this' de tipo 'T *' podría convertirse a 'volátil T *' para la llamada. – templatetypedef

+0

@templatetypedef: Invertí la lógica (aquí son solo las 7 a.m., aún necesito un poco de sueño;)). Gracias, ahora está arreglado. Puede llamar a un método 'volátil' desde una instancia' volátil' y 'no volátil'. Pero si su instancia es 'volátil', no podrá llamar a los métodos' no volátiles'. – ereOn

6

Usted no lo hace tiene que declarar explícitamente las variables miembro ..

a partir de documentos estándar 9.3.2.3,

Del mismo modo, la semántica volátiles (7.1.6.1) aplicar en funciones de miembros volátiles cuando se accede al objeto y sus miembros de datos no estáticos.

1

Así, utilizando el ejemplo originales:

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 
    } 
}; 
Cuestiones relacionadas