Según un autor conocedor dentro de la comunidad C ++, el código que se muestra a continuación no debe compilar. ¿Está equivocado?

StackOverflow https://stackoverflow.com/questions/8367459

Pregunta

Según Herb Sutter, el siguiente código no se compilaría. Ver este sitio http://www.gotw.ca/gotw/066.htm de donde he extraído el siguiente texto, con respecto function-try-blocks :

Hacia una moral

Por cierto, esto también significa que el único (repetido solo) posible uso para un bloque de función de constructor es traducir una excepción lanzada desde un subobjeto base o miembro. Eso es moral #1. A continuación, la moraleja #2 dice que los bloqueos de la función de destructores son completamente usele,

"--¡Pero espera!" Escucho a alguien interrumpiendo desde el centro de la habitación. "No estoy de acuerdo con la moral #1. ¡Puedo pensar en otro posible uso para los bloques de la función del constructor, es decir, los recursos libres asignados en la lista de inicializador o en el cuerpo del constructor!"

Lo siento, no. Después de todo, recuerde que una vez que ingrese a su manejador de try-Block de constructor, cualquier variable local en el cuerpo del constructor también ya está fuera de alcance, y se le garantiza que ya no existen subobjetos base o objetos miembros, período. Ni siquiera puedes referirte a sus nombres. O las partes de su objeto nunca fueron construidas, o las que fueron construidas ya han sido destruidas. Por lo tanto, no puede estar limpiando nada que se base en referirse a una base o miembro de la clase (y de todos modos, para eso están la base y los destructores de los miembros, ¿verdad?).

Suponiendo esta cita, el siguiente código no debe compilar, como el objeto cat ya ha sido destruido cuando el proceso se encuentra con el catch cláusula. Pero sí, al menos con VSC2008.

class Cat
{
    public:
    Cat() { cout << "Cat()" << endl; }
    ~Cat() { cout << "~Cat()" << endl; }
};

class Dog
{
    public:
    Dog() { cout << "Dog()" << endl; throw 1; }
    ~Dog() { cout << "~Dog()" << endl; }
};


class UseResources
{
    class Cat *cat;
    class Dog dog;

    public:
    UseResources();
    ~UseResources() { delete cat; cat = NULL; cout << "~UseResources()" << endl; }
};

UseResources::UseResources() try : cat(new Cat), dog() { cout << "UseResources()" << endl; } catch(...)
{
    delete cat;
    throw;
}
¿Fue útil?

Solución

No creo que Herb Sutter esté diciendo que no se compilará. Él solo está explicando las consecuencias de lo que el estándar tiene que decir sobre la situación (15.3.10):

Refiriéndose a cualquier miembro o clase base no estática de un objeto en el controlador para un bloque de funciones de un constructor o destructor para ese objeto da como resultado comportamiento indefinido.

Otros consejos

Suponiendo esta cita, el siguiente código no debe compilar ...

Bueno, él no dijo que nunca se compilarían. En todo caso, interpreté que la cita significa "hacer esto no está definido". Se permite que el comportamiento indefinido tenga algún resultado, que incluya la compilación con éxito y haciendo cosas sorprendentes más adelante.

Los compiladores son diferentes, y también hay interruptores que determinan cuánto será el compilador estricto con el código que está compilando. Este código ciertamente causará errores (fallas SEG, etc.). Intente habilitar todos los interruptores del compilador para obligarlo a encontrar esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top