variable significado significa reservadas que palabras modificador lenguaje codigos claves c++ keyword mutable

c++ - significado - que significa c#



¿La palabra clave ''mutable'' tiene algún propósito que no sea permitir que la variable sea modificada por una función const? (18)

Hace un tiempo me encontré con un código que marcaba una variable miembro de una clase con la palabra clave mutable . Por lo que puedo ver, simplemente te permite modificar una variable en un método const :

class Foo { private: mutable bool done_; public: void doSomething() const { ...; done_ = true; } };

¿Es este el único uso de esta palabra clave o hay más de lo que parece? Desde entonces, he usado esta técnica en una clase, marcando un boost::mutex como mutable, lo que permite que las funciones const lo bloqueen por motivos de seguridad de subprocesos, pero, para ser sincero, parece un poco pirateado.


Bueno, sí, eso es lo que hace. Lo uso para miembros que se modifican mediante métodos que no cambian lógicamente el estado de una clase, por ejemplo, para acelerar las búsquedas implementando un caché:

class CIniWrapper { public: CIniWrapper(LPCTSTR szIniFile); // non-const: logically modifies the state of the object void SetValue(LPCTSTR szName, LPCTSTR szValue); // const: does not logically change the object LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const; // ... private: // cache, avoids going to disk when a named value is retrieved multiple times // does not logically change the public interface, so declared mutable // so that it can be used by the const GetValue() method mutable std::map<string, string> m_mapNameToValue; };

Ahora, debe usar esto con cuidado: los problemas de concurrencia son una gran preocupación, ya que la persona que llama puede asumir que son seguros para subprocesos si solo usan métodos const . Y, por supuesto, la modificación de mutable datos mutable no debería cambiar el comportamiento del objeto de manera significativa, algo que podría violarse con el ejemplo que doy si, por ejemplo, se espera que los cambios escritos en el disco sean inmediatamente visibles para el la aplicación


El ejemplo clásico (como se mencionó en otras respuestas) y la única situación en la que he visto la palabra clave mutable utilizada hasta ahora, es para almacenar en caché el resultado de un método Get complicado, donde la caché se implementa como un miembro de datos de la clase y no como una variable estática en el método (por razones de compartir entre varias funciones o limpieza simple).

En general, las alternativas al uso de la palabra clave mutable suelen ser una variable estática en el método o el truco const_cast .

Otra explicación detallada está here .


El mutable puede ser útil cuando está anulando una función virtual constante y desea modificar su variable miembro de clase secundaria en esa función. En la mayoría de los casos, no querría alterar la interfaz de la clase base, por lo que tiene que usar su propia variable de miembro mutable.


En algunos casos (como los iteradores mal diseñados), la clase necesita mantener un recuento o algún otro valor incidental, que realmente no afecte el "estado" principal de la clase. Esto es más a menudo donde veo utilizables mutables. Sin mutable, se vería obligado a sacrificar toda la constancia de su diseño.

Se siente como un hack la mayor parte del tiempo para mí también. Útil en muy pocas situaciones.


Es útil en situaciones en las que tiene un estado interno oculto, como un caché. Por ejemplo:

class HashTable { ... public: string lookup(string key) const { if(key == lastKey) return lastValue; string value = lookupInternal(key); lastKey = key; lastValue = value; return value; } private: mutable string lastKey, lastValue; };

Y luego puede tener un objeto const HashTable que aún use su método lookup() , que modifica el caché interno.


La misma palabra clave ''mutable'' es en realidad una keyword reservada. Por lo general, se usa para variar el valor de la variable constante. Si desea tener varios valores de constsnt, use la palabra clave mutable.

//Prototype class tag_name{ : : mutable var_name; : : };


La palabra clave mutable es una forma de perforar la const que cubre sus objetos. Si tiene una referencia constante o un puntero a un objeto, no puede modificar ese objeto de ninguna manera, excepto cuándo y cómo se marca como mutable .

Con su referencia de const o puntero está limitado a:

  • Acceso de solo lectura para cualquier miembro de datos visible
  • permiso para llamar solo a los métodos que están marcados como const .

La excepción mutable hace para que ahora pueda escribir o establecer miembros de datos que estén marcados como mutable . Esa es la única diferencia externa visible.

Internamente, los métodos const que son visibles para usted también pueden escribir a los miembros de datos marcados como mutable . Esencialmente el velo constante se perfora de manera integral. Depende completamente del diseñador de API asegurarse de que mutable no destruya el concepto const y solo se use en casos especiales útiles. La palabra clave mutable ayuda porque marca claramente los miembros de datos que están sujetos a estos casos especiales.

En la práctica, puede utilizar const obsesiva en toda su base de código (esencialmente desea "infectar" su base de código con la "enfermedad" de const ). En este mundo, los punteros y las referencias son const con muy pocas excepciones, lo que genera un código que es más fácil de razonar y entender. Para una digresión interesante buscar "transparencia referencial".

Sin la palabra clave mutable , finalmente se verá obligado a utilizar const_cast para manejar los diversos casos especiales útiles que permite (almacenamiento en caché, recuento de referencias, depuración de datos, etc.). Desafortunadamente, const_cast es significativamente más destructivo que mutable porque obliga al cliente API a destruir la protección const de los objetos que está utilizando. Además, causa una destrucción generalizada const : la const_cast de un puntero o referencia constante permite la escritura sin restricciones y el acceso a los métodos a los miembros visibles. En contraste, mutable requiere que el diseñador de API ejerza un control detallado sobre las excepciones const , y generalmente estas excepciones están ocultas en los métodos const que operan en datos privados.

(Nota: me refiero a la visibilidad de los datos y los métodos varias veces. Estoy hablando de miembros marcados como públicos frente a privados o protegidos, que es un tipo de protección de objetos totalmente diferente que se trata here )


La palabra clave mutable es muy útil al crear apéndices para propósitos de prueba de clase. Puede anular una función de const y aún puede aumentar los contadores (mutables) o la funcionalidad de prueba que haya agregado a su apéndice. Esto mantiene intacta la interfaz de la clase aplastada.


Mutable cambia el significado de const de constancia bitwise a const lógica para la clase.

Esto significa que las clases con miembros mutables son más constantes a nivel de bits y ya no aparecerán en las secciones de solo lectura del ejecutable.

Además, modifica la verificación de tipos al permitir que las funciones de miembros const cambien miembros mutables sin usar const_cast .

class Logical { mutable int var; public: Logical(): var(0) {} void set(int x) const { var = x; } }; class Bitwise { int var; public: Bitwise(): var(0) {} void set(int x) const { const_cast<Bitwise*>(this)->var = x; } }; const Logical logical; // Not put in read-only. const Bitwise bitwise; // Likely put in read-only. int main(void) { logical.set(5); // Well defined. bitwise.set(5); // Undefined. }

Vea las otras respuestas para obtener más detalles, pero quería resaltar que no es solo para la seguridad de tipos y que afecta el resultado compilado.


Mutable es para marcar atributos específicos como modificables desde los métodos const . Ese es su único propósito. Piense con cuidado antes de usarlo, ya que su código probablemente será más limpio y más legible si cambia el diseño en lugar de usarlo mutable .

http://www.highprogrammer.com/alan/rants/mutable.html

Entonces, si la locura anterior no es para qué se puede cambiar, ¿para qué sirve? Aquí está el caso sutil: mutable es para el caso en el que un objeto es lógicamente constante, pero en la práctica debe cambiar. Estos casos son pocos y distantes entre sí, pero existen.

Los ejemplos que da el autor incluyen el almacenamiento en caché y las variables temporales de depuración.


Mutable se usa cuando tienes una variable dentro de la clase que solo se usa dentro de esa clase para señalar cosas como, por ejemplo, un mutex o un bloqueo. Esta variable no cambia el comportamiento de la clase, pero es necesaria para implementar la seguridad de subprocesos de la clase en sí. Por lo tanto, si sin "mutable", no podría tener funciones "const" porque esta variable deberá cambiarse en todas las funciones que están disponibles para el mundo exterior. Por lo tanto, mutable se introdujo con el fin de hacer que una variable miembro sea escribible incluso por una función const.

El mutable especificado informa tanto al compilador como al lector de que es seguro y espera que una variable miembro pueda modificarse dentro de una función miembro const.


Permite la diferenciación de constantes binarias y constantes lógicas. Constante lógica es cuando un objeto no cambia de manera que sea visible a través de la interfaz pública, como su ejemplo de bloqueo. Otro ejemplo sería una clase que calcula un valor la primera vez que se solicita, y almacena en caché el resultado.

Dado que c ++ 11 mutable se puede usar en un lambda para denotar que las cosas capturadas por valor son modificables (no son predeterminadas):

int x = 0; auto f1 = [=]() mutable {x = 42;}; // OK auto f2 = [=]() {x = 42;}; // Error: a by-value capture cannot be modified in a non-mutable lambda


Su uso con boost :: mutex es exactamente para lo que está destinada esta palabra clave. Otro uso es para el almacenamiento interno de resultados para acelerar el acceso.

Básicamente, ''mutable'' se aplica a cualquier atributo de clase que no afecte el estado visible externamente del objeto.

En el código de ejemplo de su pregunta, mutable podría ser inapropiado si el valor de done_ afecta el estado externo, depende de lo que esté en el ...; parte.


Su uso no es un hack, aunque como muchas otras cosas en C ++, mutable puede ser hack para un programador perezoso que no quiere volver atrás y marcar algo que no debería ser constante.


Uno de los mejores ejemplos en los que usamos mutables es, en copia profunda. en el constructor de copia enviamos const &obj como argumento. Así que el nuevo objeto creado será de tipo constante. Si queremos cambiar (en su mayoría no cambiaremos, en el caso raro de que cambiemos) los miembros en este objeto const recién creado necesitamos declararlo como mutable .

la clase de almacenamiento mutable se puede usar solo en un miembro de datos no constantes y no constantes de una clase. El miembro de datos mutable de una clase se puede modificar incluso si es parte de un objeto que se declara como constante.

class Test { public: Test(): x(1), y(1) {}; mutable int x; int y; }; int main() { const Test object; object.x = 123; //object.y = 123; /* * The above line if uncommented, will create compilation error. */ cout<< "X:"<< object.x << ", Y:" << object.y; return 0; } Output:- X:123, Y:1

En el ejemplo anterior, podemos cambiar el valor de la variable miembro x aunque sea parte de un objeto que se declara como constante. Esto se debe a que la variable x se declara como mutable. Pero si intenta modificar el valor de la variable miembro y , el compilador generará un error.


Use "mutable" cuando para cosas que son LOGICAMENTE sin estado para el usuario (y por lo tanto debe tener "const" getters en las API de la clase pública) pero NO son sin estado en la IMPLEMENTACIÓN subyacente (el código en su .cpp).

Los casos que uso con más frecuencia son la inicialización perezosa de miembros de "datos antiguos" sin estado. Es decir, es ideal en los casos estrechos cuando dichos miembros son caros, ya sea para compilar (procesador) o para transportar (memoria) y muchos usuarios del objeto nunca los pedirán. En esa situación, usted desea una construcción perezosa en el back-end para el rendimiento, ya que el 90% de los objetos construidos nunca tendrá que construirlos en absoluto, sin embargo, todavía debe presentar la API sin estado correcta para el consumo público.


mutable se utiliza principalmente en un detalle de implementación de la clase. El usuario de la clase no necesita saberlo, por lo tanto, el método que él piensa "debería" ser constante puede ser. Su ejemplo de tener un mutex ser mutable es un buen ejemplo canónico.


mutable existe como se infiere para permitir que uno modifique datos en una función que de otra manera sería constante.

La intención es que pueda tener una función que "no haga nada" al estado interno del objeto, por lo que marca la función const , pero es posible que realmente necesite modificar algunos de los estados del objeto de manera que no afecte su estado. funcionalidad correcta

La palabra clave puede actuar como una sugerencia para el compilador: un compilador teórico podría colocar un objeto constante (como un global) en la memoria que estaba marcado como de solo lectura. La presencia de mutable insinúa que esto no debe hacerse.

Aquí hay algunas razones válidas para declarar y usar datos mutables:

  • Hilo de seguridad. Declarar un mutable boost::mutex es perfectamente razonable.
  • Estadística. Contando el número de llamadas a una función, dados algunos o todos sus argumentos.
  • La memorización Calcular una respuesta costosa y luego almacenarla para futuras referencias en lugar de volver a calcularla.