2010-03-15 16 views
75

Tengo una pregunta acerca de la diferencia entre volátil y mutable. Noté que los dos significa que podría ser cambiado. ¿Qué más? ¿Son la misma cosa? ¿Cual es la diferencia? ¿Dónde son aplicables? ¿Por qué se proponen las dos ideas? ¿Cómo usarlos de manera diferente?volátil vs mutable en C++

Muchas gracias.

Respuesta

96

Un campo mutable se puede cambiar incluso en un objeto accede a través de un puntero const o de referencia, o en un objeto const, por lo que el compilador sabe no para guardar en la memoria R/S. Una ubicación volatile es una que se puede cambiar por código que el compilador desconoce (por ejemplo, algún controlador de nivel kernel), por lo que el compilador sabe que no se debe optimizar, p. registrar la asignación de ese valor bajo la suposición no válida de que el valor "no puede haber cambiado" desde la última vez que se cargó en ese registro. Muy diferente tipo de información que se le da al compilador para detener diferentes tipos de optimizaciones no válidas.

+12

objetos 'volátiles' también pueden ser cambiados por procesos que no involucran a la CPU en absoluto. Por ejemplo, un registro de bytes recibidos en un periférico de comunicaciones puede incrementarse en la recepción de un byte (y esto puede incluso disparar una interrupción). Otro ejemplo es un registro de indicadores de interrupción pendiente en un periférico. –

+48

Además, 'volátil' no solo significa que el objeto puede cambiar fuera del conocimiento del compilador; también significa que las escrituras en el objeto no pueden ser eliminadas por el compilador incluso si esas escrituras parecen ser inútiles. Por ejemplo: 'x = 1; x = 0; 'si' x' es volátil, el compilador debe emitir ambas operaciones de escritura (que pueden ser significativas a nivel de hardware). Sin embargo, para un objeto no volátil, el compilador podría elegir no molestarse en escribir el '1' ya que nunca se usa. –

+11

¡Un objeto se puede marcar tanto 'const' como' volátil'! No puede cambiar el objeto, pero se puede cambiar detrás de su espalda. – CTMacUser

21

Definitivamente NO son lo mismo. Mutable interactúa con const. Si tiene un puntero const, normalmente no puede cambiar los miembros. Mutable proporciona una excepción a esa regla.

Volátil, por otro lado, no tiene ninguna relación con los cambios realizados por el programa. Significa que la memoria podría cambiar por razones ajenas al control del compilador, por lo tanto, el compilador tiene que leer o escribir la dirección de memoria cada vez y no puede almacenar el contenido en un registro.

+0

* "Volátil, por otro lado, no tiene ninguna relación con los cambios realizados por el programa ..." * - hmmm, hacer que un miembro sea volátil y ver qué se rompe durante la compilación. Tratar de agregar volatilidad después del hecho es como intentar agregar const después del hecho ... Doloroso. – jww

+0

@jww: No tiene ninguna relación con las escrituras realizadas por el programa. Puede tomar la dirección de un objeto de tipo 'T', y almacenarlo en' const T * 'y leer de él. Si convierte ese objeto en "volátil", el almacenamiento de su dirección en 'const T *' fallará, aunque nunca intente escribir. 'volátil' y cambios/modificaciones/grabaciones de memoria del código del programa son completamente ortogonales. –

25

mutable: La palabra clave mutable anula cualquier instrucción const enclosure. Un miembro mutable de un objeto const se puede modificar.

volatile: La palabra clave volátil es un modificador dependiente de la implementación, que se utiliza al declarar variables, lo que impide que el compilador optimice esas variables. Volatile debe usarse con variables cuyo valor puede cambiar de forma inesperada (es decir, a través de una interrupción), lo que podría entrar en conflicto con las optimizaciones que podría realizar el compilador.

Source

+0

dijiste 'Volatile debería usarse con variables cuyo valor puede cambiar de maneras inesperadas' ¿deberíamos preferir usarlo al azar? – UnKnown

7

Una variable marcada mutable permite que se modifique en un método declarado const.

Una variable marcada volatile le dice al compilador que debe leer/escribir la variable cada vez que su código también lo dice (es decir, no puede optimizar los accesos a la variable).

13

Una forma cruda pero eficaz de pensamiento de la diferencia es:

  • El compilador sabe cuando un objeto cambia mutables.
  • El compilador no puede saber cuándo cambia un objeto volátil.
+1

En esa línea: 'volátil' bytes_received,' mutable' reference_count. –

4

me gustaría añadir que volátil es también muy útil cuando se trata de aplicaciones de subprocesos múltiples, es decir, que tenga su hilo principal (donde main() vive) y generar un subproceso de trabajo que va a seguir girando mientras una variable "app_running" es verdadero. main() controla si "app_running" es verdadero o falso, por lo que si no agrega el atributo volátil a la declaración de "app_running", si el compilador optimiza el acceso a "app_running" en el código ejecutado por el hilo secundario, main () podría cambiar "app_running" a falso, pero el subproceso secundario se seguirá ejecutando porque el valor se ha almacenado en caché. He visto el mismo comportamiento usando gcc en Linux y VisualC++. Un atributo "volátil" puesto en la declaración "app_running" resolvió el problema.Por lo tanto, este es un escenario donde no se intervienen interrupciones de hardware o kernel al cambiar el valor de dichas variables.

+0

¡No! Este es un malentendido común. C++ 11 y C11 introdujeron átomos para este fin http://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model – KristianR