Tenga en cuenta que si esto califica para usted, pero en lenguajes funcionales como Standard ML, todo es inmutable de manera predeterminada. La mutación es compatible a través de un reftipo de diferencia genérico . Entonces, una intvariable es inmutable, y una ref intvariable es un contenedor mutable para ints. Básicamente, las variables son variables reales en el sentido matemático (un valor desconocido pero fijo) y las refs son "variables" en el sentido de programación imperativo, una celda de memoria en la que se puede escribir y leer. (Me gusta llamarlos asignables ).
Creo que el problema constes doble. Primero, C ++ carece de recolección de basura, lo cual es necesario para tener estructuras de datos persistentes no triviales . const debe ser profundo para que tenga sentido, pero tener valores totalmente inmutables en C ++ no es práctico.
En segundo lugar, en C ++ debe optar por participar en constlugar de rechazarlo. Pero cuando se olvida de constalgo y luego lo arregla, terminará en la situación de "envenenamiento constante" mencionada en la respuesta de @ RobY, donde el constcambio caerá en cascada a lo largo del código. Si constfuera el predeterminado, no se encontraría aplicando constretroactivamente. Además, tener que agregar en consttodas partes agrega mucho ruido al código.
Sospecho que los lenguajes principales que siguieron (por ejemplo, Java) fueron fuertemente moldeados por el éxito y la forma de pensar de C y C ++. Caso en cuestión, incluso con la recolección de basura, la mayoría de las API de recolección de idiomas asumen estructuras de datos mutables. El hecho de que todo sea mutable y la inmutabilidad se vea como un caso de esquina habla mucho sobre la mentalidad imperativa detrás de los lenguajes populares.
EDITAR : Después de reflexionar sobre el comentario de Greenoldman, me di cuenta de que constno se trata directamente de la inmutabilidad de los datos; constcodifica en el tipo de método si tiene efectos secundarios en la instancia.
Es posible usar la mutación para lograr un comportamiento referencialmente transparente . Suponga que tiene una función que, cuando se llama sucesivamente, devuelve valores diferentes, por ejemplo, una función que lee un solo carácter stdin. Podríamos usar caché / memorizar los resultados de esta función para producir un flujo de valores referencialmente transparente. La secuencia sería una lista vinculada cuyos nodos llamarán a la función la primera vez que intente recuperar su valor, pero luego almacenar en caché el resultado. Entonces, si stdinconstains Hello, world!, la primera vez que intente recuperar el valor del primer nodo, leerá uno chary regresará H. Luego continuará regresando Hsin más llamadas para leer a char. Del mismo modo, el segundo nodo leería una chardestdinla primera vez que intente recuperar su valor, esta vez devuelve ey almacena en caché ese resultado.
Lo interesante aquí es que ha convertido un proceso inherentemente con estado en un objeto que aparentemente no tiene estado. Sin embargo, fue necesario mutar el estado interno del objeto (almacenando en caché los resultados) para lograr esto: la mutación fue un efecto benigno . Es imposible hacer nuestro CharStream consta pesar de que la transmisión se comporta como un valor inmutable. Ahora imagine que hay una Streaminterfaz con constmétodos y que todas sus funciones esperan const Streams. ¡No CharStreampuedes implementar la interfaz!
( EDITAR 2: Aparentemente hay una palabra clave de C ++ llamada mutableque nos permitiría hacer trampa y hacerCharStream const . Sin embargo, esta escapatoria destruye constlas garantías, ahora realmente no puedes estar seguro de que algo no mutará a través de sus constmétodos. Supongo que no es eso malo, ya que debe solicitar explícitamente la escapatoria, pero aún depende completamente del sistema de honor).
En segundo lugar, suponga que tiene funciones de orden superior, es decir, puede pasar funciones como argumentos a otras funciones. constness es parte de la firma de una función, por lo que no podrá pasar las no constfunciones como argumentos a las funciones que esperan constfunciones. Hacer cumplir ciegamente constaquí conduciría a una pérdida de generalidad.
Finalmente, manipular un constobjeto no garantiza que no esté mutando algún estado externo (estático o global) a sus espaldas, por lo que constlas garantías no son tan fuertes como parecen inicialmente.
Para mí no está claro que codificar la presencia o ausencia de efectos secundarios en el sistema de tipos sea universalmente una buena cosa.