c++ - Singleton con un objeto que tira en el ctor-¿accediendo de nuevo?




exception memory-management (2)

Puedo usar C ++ 11 o C ++ 14 (o incluso C ++ 17). Supongamos que tengo un objeto singleton


class MyInstance {
public:
    MyInstance() {
        throw std::runtime_exception("something went wrong"); // Ctor might throw
    }
};

MyInstance& getInstance() {
    static MyInstance obj;
    return obj;
}

Ahora, me aseguré de que cada llamada a getInstance esté envuelta en un

try {
    auto& inst = getInstance();
} catch(std::runtime_error& e) {
   // do something
}

Lo que me pregunto ahora es: ¿qué sucede si después de fallar una inicialización en el constructor y arrojar, atrapar e informar al usuario en los registros ... el programa pasa nuevamente en una ruta de código de try y vuelve a llamar a getInstance ?

Hice algunas conjeturas pero no tengo idea si tienen razón:

El objeto tiene almacenamiento estático, por lo que solo se intentará construir una vez que lo piense. ¿Devolver una referencia a un objeto no construido me dará una referencia colgante y un comportamiento indefinido? ¿ unique_ptr un unique_ptr como variable estática en lugar de obj resolver este problema para que pueda acceder al puntero varias veces y también verificar si el objeto se construyó correctamente ( if (uptr == TRUE) )?


[stmt.dcl]/4: la inicialización dinámica de una variable de alcance de bloque con duración de almacenamiento estático o duración de almacenamiento de subprocesos se realiza la primera vez que el control pasa por su declaración; dicha variable se considera inicializada una vez completada su inicialización. Si la inicialización sale lanzando una excepción, la inicialización no está completa, por lo que se volverá a intentar la próxima vez que el control ingrese la declaración. [..]

No hay necesidad de "adivinar"; puede poner un seguimiento std::cout dentro de MyInstance::MyInstance() y llamar a getInstance() dos veces . 😊

Tampoco hay necesidad de punteros inteligentes; el objeto existe o no, y no hay forma de proceder dentro de getInstance() después de la declaración sin el objeto existente, ¡porque arrojó una excepción!

Por cierto, es std::runtime_error , no std::runtime_exception .


Si el constructor lanza el objeto no se inicializa. Por lo tanto, si el control vuelve a pasar por getInstance , la inicialización también se realizará nuevamente.

[stmt.dcl] (énfasis mío)

4 La inicialización dinámica de una variable de alcance de bloque con duración de almacenamiento estático o duración de almacenamiento de subprocesos se realiza la primera vez que el control pasa por su declaración; dicha variable se considera inicializada una vez completada su inicialización. Si la inicialización sale lanzando una excepción, la inicialización no está completa, por lo que se volverá a intentar la próxima vez que el control ingrese la declaración . Si el control ingresa la declaración concurrentemente mientras se inicializa la variable, la ejecución concurrente esperará la finalización de la inicialización. Si el control vuelve a ingresar la declaración de forma recursiva mientras se inicializa la variable, el comportamiento es indefinido.





unique-ptr