Estoy interesado en la idea de C ++, como constno esa ejecución particular (como desechar const).
Tomemos, por ejemplo, C #: carece de C ++, como const, y la razón es la habitual: personas y tiempo. Aquí, además, parece que el equipo de C # analizó la ejecución de C ++ de constCLR de marketing y tuvo suficiente en este punto (vea por qué no hay un método de miembro const en C # y parámetro const ; gracias Svick). Si nos movemos más allá de eso, ¿hay algo más?
¿Hay algo más profundo? Tomemos, por ejemplo, la herencia múltiple: por lo general, se considera difícil de entender (para el usuario) y, por lo tanto, no se agrega al idioma (como el problema del diamante).
¿Hay algo en NATURE de constque representan un problema de que es mejor para el lenguaje para evitarlo? Algo así como decidir si constdebe ser profundo o poco profundo (tener constcontenedor significa que no puedo agregar un nuevo elemento o alterar elementos existentes también; ¿qué pasa si los elementos son del tipo de referencia)?
ACTUALIZACIÓN : si bien menciono C # y, por lo tanto, hago una perspectiva histórica, estoy interesado en la naturaleza de los posibles problemas del constlenguaje.
Este no es un desafío de los idiomas. Ignore factores como las tendencias actuales o la popularidad. Solo estoy interesado en cuestiones técnicas. Gracias.
fuente

Respuestas:
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, unaintvariable es inmutable, y unaref intvariable es un contenedor mutable paraints. Básicamente, las variables son variables reales en el sentido matemático (un valor desconocido pero fijo) y lasrefs 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 .constdebe 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 deconstalgo y luego lo arregla, terminará en la situación de "envenenamiento constante" mencionada en la respuesta de @ RobY, donde elconstcambio caerá en cascada a lo largo del código. Siconstfuera el predeterminado, no se encontraría aplicandoconstretroactivamente. Además, tener que agregar enconsttodas 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, sistdinconstainsHello, world!, la primera vez que intente recuperar el valor del primer nodo, leerá unochary regresaráH. Luego continuará regresandoHsin más llamadas para leer achar. Del mismo modo, el segundo nodo leería unachardestdinla primera vez que intente recuperar su valor, esta vez devuelveey 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
CharStreamconsta pesar de que la transmisión se comporta como un valor inmutable. Ahora imagine que hay unaStreaminterfaz conconstmétodos y que todas sus funciones esperanconst Streams. ¡NoCharStreampuedes implementar la interfaz!( EDITAR 2: Aparentemente hay una palabra clave de C ++ llamada
mutableque nos permitiría hacer trampa y hacerCharStreamconst. Sin embargo, esta escapatoria destruyeconstlas garantías, ahora realmente no puedes estar seguro de que algo no mutará a través de susconstmé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 noconstfunciones como argumentos a las funciones que esperanconstfunciones. Hacer cumplir ciegamenteconstaquí 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 queconstlas 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.
fuente
varbajo demanda dejaría solo un problema: ¿la profundidad?constreferencia a un noconstobjeto. Aun así, no creo que tenga sentido tener una superficialidadconst. El objetivoconstes garantizar que no podrá modificar el objeto a través de esa referencia. No está permitido eludirconstcreando una noconstreferencia, entonces, ¿por qué estaría bien eludirconstmutando los miembros del objeto?func foo(const String &s)y esta es una señalsque no se cambiaráfoo.nullherencia).El principal problema es que los programadores tienden a no usarlo lo suficiente, por lo que cuando llegan a un lugar donde se requiere, o un responsable de mantenimiento más tarde quiere corregir la corrección constante, hay un gran efecto dominó. Todavía puede escribir código inmutable perfectamente bueno sin
const, su compilador simplemente no lo hará cumplir, y tendrá más dificultades para optimizarlo. Algunas personas prefieren que su compilador no los ayude. No entiendo a esas personas, pero hay muchas.En lenguajes funcionales, casi todo lo es
const, y ser mutable es la rara excepción, si es que está permitido. Esto tiene varias ventajas, como una concurrencia más fácil y un razonamiento más fácil sobre el estado compartido, pero lleva un tiempo acostumbrarse si viene de un idioma con una cultura mutable. En otras palabras, no quererconstes un problema de personas, no técnico.fuente
Veo los inconvenientes como:
"envenenamiento const" es un problema cuando una declaración de const puede obligar a una declaración anterior o siguiente a usar const, y eso puede hacer que sus declaraciones anteriores o siguientes usen const, etc. Y si el envenenamiento const fluye a una clase en una biblioteca sobre el que no tienes control, entonces puedes quedarte atrapado en un mal lugar.
No es una garantía absoluta. Por lo general, hay casos en los que la constante solo protege la referencia, pero no puede proteger los valores subyacentes por una razón u otra. Incluso en C, hay casos extremos que const no puede alcanzar, lo que debilita la promesa que ofrece const.
en general, el sentimiento de la industria parece estar alejándose de las fuertes garantías en tiempo de compilación, por mucho consuelo que puedan brindarle a usted y a mí. Así que por la tarde pasé tocando el 66% de mi base de código debido al envenenamiento constante, algunos Python Guy ha lanzado 10 módulos Python perfectamente funcionales, bien diseñados, probados y totalmente funcionales. Y ni siquiera estaba pirateando cuando lo hizo.
Entonces, tal vez la pregunta sea, ¿por qué llevar a cabo una característica potencialmente controvertida que incluso algunos expertos son ambivalentes cuando intentas adoptar tu nuevo lenguaje elegante?
EDITAR: respuesta corta, un nuevo idioma tiene que subir una colina empinada para su adopción. Sus diseñadores realmente necesitan pensar mucho sobre qué características necesita para obtener la adopción. Take Go, por ejemplo. Google truncó brutalmente algunas de las batallas religiosas más profundas al hacer algunas elecciones de diseño de estilo Conan-the-Barbarian, y realmente creo que el lenguaje es mejor para eso, por lo que he visto.
fuente
int *puntero mutable a valor mutable,int const *puntero mutable a valorint * constconstante , puntero constante a valor mutable,int const * constpuntero constante a valor constante.const), por lo tanto, tales "razones" considero irrelevantes (al menos para esta pregunta). Sobre elconstenvenenamiento, ¿puedes dar un ejemplo? Porque AFAIK es la ventaja, pasas algoconsty debe permanecerconst.constproblema, sino cambiar el tipo realmente; hagas lo que hagas, siempre será un problema. Considere pasarRichString, y luego darse cuenta de que es mejor pasarString.const. Es demasiado fácil no hacer lasconstcosas que deberían serconstporque tienes que optar por él en lugar de salir de él.Hay algunos problemas filosóficos al agregar
constun idioma. Si declaraconsta una clase, eso significa que la clase no puede cambiar. Pero una clase es un conjunto de variables junto con métodos (o mutadores). Logramos la abstracción al ocultar el estado de una clase detrás de un conjunto de métodos. Si una clase está diseñada para ocultar el estado, entonces necesita mutadores para cambiar ese estado desde el exterior y ya no lo esconst. Por lo tanto, solo es posible declararconsta las clases que son inmutables. Entonces,constparece posible solo en escenarios donde las clases (o los tipos que desea declararconst) son triviales ...Entonces, ¿necesitamos de
consttodos modos? No lo creo. Creo que puedes prescindir fácilmenteconstsi tienes un buen diseño. Qué datos necesita y dónde, qué métodos son métodos de datos a datos y qué abstracciones necesita para E / S, red, vista, etc. Luego, naturalmente, divide módulos y clases que se ocupan del estado y tiene métodos y métodos. clases inmutables que no necesitan estado.Creo que la mayoría de los problemas surgen con objetos de datos grandes y gordos que pueden guardarse, transformarse y dibujarse y luego desea pasarlos a un renderizador, por ejemplo. Por lo tanto, no puede copiar el contenido de los datos, porque es demasiado costoso para un gran objeto de datos. Pero tampoco quieres que cambie, así que necesitas algo como
constpiensas. Deje que el compilador descubra sus defectos de diseño. Sin embargo, si divide esos objetos solo en un objeto de datos inmutable e implementa los métodos en el módulo responsable, puede pasar (solo) el puntero y hacer las cosas que desea hacer con los datos al tiempo que garantiza la inmutabilidad.Sé que en C ++ es posible declarar algunos métodos
consty no declarar otros métodos, porque son mutadores. Y luego, un tiempo después, necesita un caché y luego un getter muta un objeto (porque se carga lentamente) y ya no lo esconst. Pero ese era el objetivo de esta abstracción, ¿verdad? No sabes qué estado se muta con cada llamada.fuente
const(en sentido C ++ ) debe definir la interfaz, también para todas las propiedades.