¿Las variables miembro no estáticas en una estructura/clase de C++ deben marcarse como volátiles para ser tratadas como volátiles en una función miembro?

4 minutos de lectura

Avatar de usuario de 0xbadf00d
0xbadf00d

class MyClass
{
    int x, y;
    void foo() volatile {
        // do stuff with x
        // do stuff with y
    }   
};

¿Necesito declarar? x y y como volatile o serán todas las variables miembro tratadas como volatile ¿automáticamente?

Quiero asegurarme de que “cosas con x” no se reordena con ” cosas con y” por el compilador.

EDITAR: ¿Qué sucede si estoy lanzando un tipo normal a un volatile ¿tipo? ¿Esto indicaría al compilador que no reordene 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 asegurarme de que el compilador no reordene esa llamada con lecturas y escrituras anteriores o seguidas.

  • relacionado stackoverflow.com/questions/2444734/…

    – Peter Cordes

    9 de septiembre de 2016 a las 0:09

avatar de usuario de templatetypedef
templatetypedef

Marcar una función miembro volatile es como marcarlo const; significa que el objeto receptor se trata como si fuera declarado como un volatile T*. En consecuencia, cualquier referencia a x o y será tratado como un volatile leer en la función miembro. Además, un volatile el objeto solo puede llamar volatile funciones de miembro.

Dicho esto, es posible que desee marcar x y y volatile de todos modos, si realmente desea que todos los accesos a ellos sean tratados como volatile.

no tiene que declarar las variables miembro explícitamente ..

De documentos estándar 9.3.2.3,

Similarmente, semántica volátil (7.1.6.1) aplicar en funciones de miembros volátiles al acceder al objeto y sus miembros de datos no estáticos.

Avatar de usuario de ereOn
ereOn

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

Genera un error al compilar 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 desde un volatile instancia no puede llamar a un non-volatile método, podemos suponer que, sí, x y y será volatile en el método, incluso si la instancia de MyClass no se declara volatile.

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

  • Corríjame si me equivoco en esto, pero ¿la semántica de las funciones volátiles no es como la de las funciones constantes en el sentido de que puede llamar a una función volátil en un objeto no volátil, pero no a una función no volátil de un objeto volátil?

    – templatetypedef

    28 de enero de 2011 a las 9:47

  • @ereOn- Una prueba rápida en g++ sugiere que sí puedes llamar volatile funciones miembro de on-volatile objetos. La razón que volatile std::strings son inútiles es porque si la cadena en sí es volatilesolo puede llamar volatile funciones miembro, de las cuales no hay ninguna. $4.4.1 del estándar aclara que puede convertir un T* en un T* volátil implícitamente, y $9.3.1.3 dice que el volatile El calificador afecta al this puntero, lo que sugiere que si tiene un objeto de tipo Tel this puntero de tipo T* podría convertirse en un volatile T* para la llamada

    – templatetypedef

    28 de enero de 2011 a las 9:56

  • @templatetypedef: Invertí la lógica (solo son las 7 am aquí; todavía necesito dormir un poco;)). Gracias, ya está arreglado. Puedes llamar a un volatile método de ambos volatile y non-volatile instancia. Pero si tu instancia es volatile no podrás llamar non-volatile métodos.

    – ereOn

    28 de enero de 2011 a las 9:57


  • @ereOn: Entonces, es exactamente como para const, como dijo templatetypedef. La parte relevante, por supuesto, no es g ++, sino el estándar: la cláusula 4.4.1 parece indicarme que la necesaria conversión implícita de this de T* a volatile T* era completamente legal. También tenga en cuenta que 9.3.2.4 dice explícitamente que puede realizar una llamada a una función calificada cv si la expresión de objeto en la que la invoca es “tan calificada como cv o menos calificada como cv que la función miembro”. No se hace diferencia entre const y volatile en esta área.

    –Christopher Creutzig

    28 de enero de 2011 a las 10:18


  • En cuanto a la conversión: si el objeto original en realidad se definió como volátil y accede a este objeto o a uno de sus miembros como un valor l (esencialmente, en el lado izquierdo de una asignación) como algo no volátil, cláusula 7.1.5.1.7 del estándar dice que el comportamiento del programa no está definido. No haga eso, incluso si funciona con la versión actual de su compilador actual en sus datos de prueba actuales. AFAICS, el elenco estaría bien para el acceso de solo lectura, al igual que para const.

    –Christopher Creutzig

    28 de enero de 2011 a las 10:26

Así que usando el ejemplo original:

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

¿Ha sido útil esta solución?