tipos que implementa ejemplos definicion copia constructores como c++ exception c++11 move-semantics

c++ - que - ¿Por qué lanzar la variable local invoca el constructor de movimientos?



que es un destructor en c++ (2)

Recientemente, he "jugado" con valores para entender su comportamiento. La mayoría de los resultados no me sorprendieron, pero luego vi que si lanzo una variable local, se invoca el constructor de movimientos.

Hasta entonces, pensé que el propósito de las reglas de semántica de movimientos es garantizar que el objeto se moverá (y se volverá inválido) solo si el compilador puede detectar que ya no se usará (como en objetos temporales), o el usuario no promete para usarlo (como en std :: mover).

Sin embargo, en el siguiente código, ninguna de estas condiciones se mantuvo, y mi variable aún se está moviendo (al menos en g ++ 4.7.3).

¿Porqué es eso?

#include <iostream> #include <string> using namespace std; int main() { string s="blabla"; try { throw s; } catch(...) { cout<<"Exception!/n"; } cout<<s; //prints nothing }


El estándar C ++ dice (15.1.3):

Lanzar una copia de excepción : inicializa (8.5, 12.8) un objeto temporal , llamado objeto de excepción. El temporal es un lvalue y se usa para inicializar la variable nombrada en el controlador de coincidencia (15.3).

Este párrafo también puede ser relevante aquí (12.8.31):

Cuando se cumplen ciertos criterios, una implementación puede omitir la construcción de copia / movimiento de un objeto de clase, incluso si el constructor seleccionado para la operación de copiar / mover y / o el destructor para el objeto tienen efectos secundarios . En tales casos, la implementación trata el origen y el destino de la operación de copiar / mover omitida como simplemente dos formas diferentes de referirse al mismo objeto, y la destrucción de ese objeto ocurre en el momento posterior en que los dos objetos habrían sido destruido sin la optimización. Esta elisión de las operaciones de copiar / mover, llamada copia elisión, está permitida en las siguientes circunstancias (que pueden combinarse para eliminar copias múltiples):

(...)

- en una expresión de proyección , cuando el operando es el nombre de un objeto automático no volátil (que no sea una función o parámetro catch-clause) cuyo alcance no se extiende más allá del final del try-block circundante más interno (si existe uno) , la operación de copiar / mover desde el operando al objeto de excepción (15.1) se puede omitir al construir el objeto automático directamente en el objeto de excepción

Controlado en Visual Studio 2012, efecto:

Exception! blabla

Parece un error en GCC de hecho.


En el caso dado, probablemente sea un error del compilador, porque la variable lanzada (y movida) se referencia posteriormente.

En general, invocar el movimiento en movimiento es conceptualmente lo mismo que avanzar en el return . Es bueno invocar el movimiento automáticamente cuando se sabe que no se pudo hacer referencia a la variable después del punto dado ( throw o return ).