const le dice al compilador que la variable es inmutable (no puede ser cambiada después de la inicialización). Se utiliza para declarar variables constantes, así como para métodos que garantizan no modificar el estado del objeto.
mutable permite modificar el valor de un campo de clase incluso dentro de métodos const.
volatile le dice al compilador que el valor de la variable puede cambiar fuera del control del programa (por ejemplo, por hardware), y el compilador no debe optimizar los accesos a ella.
class Logger { public: void log() const { ++count; // Permitido — count se declara mutable } private: mutable int count = 0; }; volatile int flag; void wait() { while (flag == 0) { /* el compilador no optimiza el bucle, ya que flag es volatile */ } }
«¿Qué sucederá si se declara un miembro de la clase como
constymutableal mismo tiempo?»
Respuesta: No se puede hacer, son calificadores mutuamente excluyentes; el compilador generará un error.
Historia
En software industrial para trabajar con hardware, el desarrollador declaró datos, actualizados por interrupciones externas, como enteros normales. La optimización del compilador eliminó lecturas repetidas de estas variables, lo que hizo que el programa "se bloqueara" en un bucle infinito. El problema se diagnosticó solo después de cambiarlos a
volatile int.
Historia
Una de las clases de registro tenía un método
log() const, donde se requería actualizar el contador de llamadas. Al principio, se hacía a través del punteroconst_cast, lo que causó muchas advertencias y errores no evidentes. El problema desapareció después de declarar correctamente el contador comomutable.
Historia
Algunos métodos de la clase se declararon como
const, pero los miembros de tipo puntero cambiaban (por ejemplo, para implementar la caché). Esto llevó a violaciones de la lógica de "const-correctness" e incluso UB, si el objeto realmente se ubicaba en una zona de solo lectura. Se debería haber utilizadomutableo cambiado el diseño.