2012-04-11 10 views
11

Me he encontrado con un problema de excepciones que no está claro para mí. En C++, cuando se lanza un objeto, primero se copia a un objeto temporal, y el objeto temporal se pasa luego al código de captura. La copia implica el uso del constructor de copia de clase del objeto. AFAIK, esto significa que si una clase tiene un constructor de copia privada, no se puede usar como una excepción. Sin embargo, en VS2010, el siguiente código se compila y ejecuta:¿Se pueden lanzar objetos con constructores de copia privada?

class Except 
{ 
    Except(const Except& other) { i = 2; } 
public: 
    int i; 
    Except() : i(1) {} 
}; 

int main() 
{ 
    try 
    { 
     Except ex1; 
     throw ex1;   // private copy constructor is invoked 
    } 
    catch (Except& ex2) 
    { 
     assert(ex2.i == 2); // assert doesn't yell - ex2.i is indeed 2 
    } 
    return 0; 
} 

¿Es esto legal?

+0

Trate de añadir las impresiones o depuración y ver el orden de las llamadas, tal vez las cosas no se ejecutan exactamente como crees que lo hacen. – selalerer

+1

Obtengo el mismo comportamiento con VS2010 pero falla [aquí] (http://ideone.com/RlOjl) con gcc v4.3.4. – hmjd

+0

Podría ser que el objeto temporal sea lo que se construye y la copia se optimice. Similar a la optimización del valor de retorno. –

Respuesta

13

No es legal. Estándar 15,1/5

Si el uso del objeto temporal puede ser eliminado sin cambiar el significado del programa excepto para la ejecución de constructores y destructores asociado con el uso del objeto temporal (12.2), a continuación, la excepción en el controlador se puede inicializar directamente con el argumento de la expresión throw. Cuando el objeto lanzado es un objeto de clase y no se puede acceder al constructor de copia utilizado para inicializar la copia temporal , el programa está mal formado (incluso cuando el objeto temporal podría eliminarse). Del mismo modo, si el destructor para ese objeto no es accesible, el programa es mal formado (incluso cuando el objeto temporal podría ser eliminado).

+0

Guau, eso es increíble, nunca hubiera adivinado que podría suceder. gracias. – petric

2

No, no lo es.

15.1.5 Cuando el objeto lanzado es un objeto de la clase, la copia/movimiento constructor y el destructor será accesible, incluso si la operación de copia/movimiento se elide

Cuestiones relacionadas