static_cast cast c++ reference const const-cast temporary-objects

c++ - static_cast - ¿Estoy en lo cierto al decir que const_cast seguido de modificación en un ref-to-const vinculado a un temporal está bien?



static cast (2)

Me gustaría verificar mi comprensión y conclusiones sobre este asunto.

En IRC, se le preguntó:

¿Es aceptable const_cast una referencia const que está vinculada a un objeto temporal?

Traduciendo: tiene un ref-to-const ligado a un temporal, y quiere desechar su const -ness para modificarlo.

Mi respuesta fue que había hecho una pregunta similar anteriormente, donde el consenso parecía ser que los propios temporales no son intrínsecamente consustanciales, y por lo tanto que puedes desechar la const -ness de una referencia que tienes para ellos, y modificarlos a través de el resultado. Y, mientras exista ese ref-to- const original, esto no afectará la vida del temporal.

Es decir:

int main() { const int& x = int(3); int& y = const_cast<int&>(x); y = 4; cout << x; } // Output: 4 // ^ Legal and safe

¿Estoy en lo cierto?

(Por supuesto, si ese código es o no aconsejable es otro asunto completamente diferente).


La respuesta depende de cómo se crea el temporal y cómo se inicializa la referencia.

Si creaste explícitamente el objeto temporal como un objeto de tipo no const y la situación garantiza que la referencia const se adjunta específicamente al temporal que has creado, entonces puedes descartar con seguridad la constness de la referencia y modificar el objeto.

Por otro lado, si el compilador creó implícitamente el temporal, entonces el temporal en sí será const. En ese caso, modificar ese temporal conduce a UB.

Desafortunadamente, el estándar de lenguaje C ++ en sí mismo no parece garantizar ninguna situación en la que necesariamente se adopte el primer enfoque de inicialización. En cualquier contexto, el compilador puede introducir una copia temporal adicional de su original temporal. El nuevo temporal será const (como se indicó anteriormente) y, por lo tanto, no modificable. Si esto sucede o no, está definido por la implementación, como se indica en 8.5.3 / 5.

Entonces, en el caso general, la respuesta es no, mientras que una respuesta específica a la implementación puede ser diferente.


No.

Primero, hasta donde puedo decir, si es literal o no es irrelevante. Los valores R de tipos no de clase siempre tienen tipos calificados no cv (§3.10 / 9), sin embargo, en §8.5.3 (inicialización de una referencia), tenemos:

Una referencia al tipo "cv1 T1" se inicializa con una expresión del tipo "cv2 T2" de la siguiente manera:

[...]

-

De lo contrario, se crea un temporal de tipo "cv1 T1" y se inicializa a partir de la expresión del inicializador utilizando las reglas para una inicialización de copia sin referencia (8.5). La referencia está vinculada a lo temporal. Si T1 está relacionado con la referencia a T2, cv1 debe ser de la misma calificación de cv o mayor cvalificación que, cv2; de lo contrario, el programa está mal formado.

(Todos los puntos anteriores se refieren a lvalues ​​o tipos de clases).

En nuestro caso, tenemos:

int const& x = ...;

Entonces cv1 T1 es int const , y el objeto temporal que creamos tiene type int const . Este es un const de nivel superior (en el objeto), por lo que cualquier intento de modificarlo es un comportamiento indefinido.

Al menos, esa es mi interpretación. Ojalá el estándar fuera un poco más claro sobre esto.