2012-05-16 14 views
5

código dado como la siguiente:¿Puede una asignación literal a int en C++ lanzar una excepción?

void f() 
{ 
    int i; 
    i = 0; 
} 

es posible que el sistema podría lanzar una excepción debido a la simple tarea?

[Editar: Para aquellos que dicen: "No se puede producir una excepción", ¿me puede apuntar en la dirección de la parte del estándar de C++ que dice esto? Tengo problemas para encontrarlo.]

+6

es el tipo siempre 'int' y el RHS siempre es literal? ¿O preguntas sobre el caso general? (También lo que mostraste no era una tarea) – Flexo

+0

Gracias por captar ese punto. Edité el ejemplo. Para su primera pregunta, para ambos, en realidad. –

Respuesta

7

Aunque probablemente sea difícil encontrarle una garantía en el estándar, una simple regla general es que cualquier cosa que sea legítima en C probablemente no pueda arrojarse. [Editar: Lo más cerca que estoy al tanto de que una declaración directa en este sentido es en el § 15/2, que dice que:

código que se ejecuta un saque de banda expresión se dice que es “una excepción ”[...]

cuanto a que a la inversa, código que no ejecuta un saque de banda expresión no lanzar una excepción]

lanzar se limita fundamentalmente a dos posibilidades. la primera es invocando a UB. El segundo es hacer algo exclusivo de C++, como asignar a un tipo definido por el usuario que sobrecarga operator =, o usar una expresión new.

Editar: En lo que respecta a una tarea, hay bastantes maneras en que puede arrojar. Obviamente, lanzar el propio operador de asignación lo haría, pero hay un buen número de otros. Solo por ejemplo, si el tipo de fuente no coincide con el tipo de destino, puede obtener una conversión a través de un operador de conversión en la fuente o un constructor en el destino, cualquiera de los cuales podría arrojar.

+0

Las implementaciones son libres de imponer límites a los recursos, ¿no es así? Si no lo fueran, "no más pilas y ningún registro de repuesto" (al menos teóricamente), ¿sería una razón válida para tirar y solo se detectaría en el primer uso? – Flexo

+0

En teoría sí. VC++ 6 (por ejemplo) hizo cosas como esa, pero funcionó lo suficientemente mal como para que VC++ ya no lo haga, y me sorprendería al menos ver que alguien más lo intente pronto. –

+0

@JerryCoffin Para una definición suficientemente estricta de "legítimo en C". Asignar un punto flotante a un int puede dar como resultado un comportamiento indefinido, y una excepción es tan válida como cualquier otra cosa en el caso de un comportamiento indefinido (aunque tal vez no desde el punto de vista de la calidad de implementación). –

0

si es solo un int, entonces no, no lo lanzará.

si se trata de algo más complejo, como un vector, puede aparecer por varios motivos (por ejemplo, error de asignación o alteración de un hilo secundario).

+0

La falla de asignación se define para arrojar una excepción (a menos que esté usando un asignador personalizado). Acceder a un vector de otro hilo mientras lo modifica es un comportamiento indefinido, y cualquier cosa puede suceder. Desde el punto de vista de la calidad de implementación, sin embargo, no esperaba una excepción. –

2

Puede arrojar una excepción solo en un caso: cuando se sobrecarga operator=() para esos dos tipos arroja; Similarmente, cuando se necesita conversión, el constructor de conversión o operator T() también puede arrojar. Depende de la implementación exacta en ese momento: para saber si se lanzará, busque información al respecto en la documentación de la biblioteca que está utilizando.

6

Hay una gran cantidad de cosas que se parecen a las asignaciones que pueden lanzar una u otra manera:

int operator"" _t(const char *) { throw 0; } // C++11 user defined literal 

struct foo { 
    foo(int) { throw 0; } 
    operator int() { throw 0; } 
    foo& operator=(int) { throw 0; } 
}; 

int main() { 
    int i; 
    i = 0; // can't throw 
    i = 0_t; // User defined literal throws 
    foo f = 0; // Constructor throws 
    i = f; // conversion operator throws 
    f = 0; // assignment throws 
    f = f; // both conversion and assignment would like to throw 
} 

(incluyendo la nueva de C++ 11)

3

Si le preocupa Asignar 0 (que tiene el tipo int) a int, el §5.17 del estándar especifica exactamente la semántica de la operación de asignación , y no hay ningún caso en que pueda ocurrir una excepción. Si usted está preocupado acerca de la asignación de una expresión arbitraria a una int, §5.17 dice que “ la expresión se convierte implícitamente al tipo cv-no calificado del operando de la izquierda."Dependiendo del tipo real del operando de la derecha:

  • Si se trata de un tipo entero, si el valor real no puede ser representado en una int, los resultados son definidos por la implementación (el estándar de C es más explícito: debe dar como resultado un int con un valor de implementación definido, o obtendrá una señal de implementación definida)

  • Si es un valor de coma flotante, el resultado es un comportamiento indefinido si el valor después del truncamiento a cero no se puede representar en un int, el comportamiento no está definido (por lo que puede obtener una excepción)

  • Si se trata de un tipo definido por el usuario, se llamará a un operador de conversión definido por el usuario. Que puede arrojar una excepción.

Si usted está preocupado acerca de la asignación de otros tipos: para cada conjunto de tipos no de clase, hay una lista de reglas como la anterior, pero las únicas excepciones posibles habrá como resultado de una tipo de conversión. Para los tipos de clase , se usará operator=. Que puede arrojar una excepción, dependiendo de lo que contenga.

Cuestiones relacionadas