liste - costruttore virtuale c++



Il costruttore termina lanciando un'eccezione? C'è una perdita di memoria? (2)

Stavo esaminando questo articolo e si afferma

Nota: se un costruttore termina lanciando un'eccezione, la memoria associata all'oggetto stesso viene ripulita: non vi è perdita di memoria. Per esempio:

void f()
{
X x; // If X::X() throws, the memory for x itself will not leak
Y* p = new Y(); // If Y::Y() throws, the memory for *p itself will not leak
}

Sto avendo difficoltà a capire questo e apprezzerei se qualcuno potesse chiarirlo. Ho provato il seguente esempio che mostra che nel caso di un'eccezione all'interno di un costruttore il distruttore non verrebbe chiamato.

struct someObject
{
    someObject()
    {
      f = new foo();    
      throw 12;
    }
    ~someObject()
    {
        std::cout << "Destructor of someobject called";
    }

    foo* f;
};

class foo
{
public:
    foo()
    {
            g = new glue();
            someObject a;
    }
    ~foo()
    {
        std::cout << "Destructor of foo";
    }
 private:
  glue* g;
};


int main()
{
    try
    {
        foo a;
    }
    catch(int a)
    {
        //Exception caught. foo destructor not called and someobject destrucotr not called.
       //Memory leak of glue and foo objects
    }
}

Come risolverei questo problema?

Ci scusiamo per l'inconveniente che l'aggiornamento potrebbe aver causato.


"... il distruttore non verrebbe chiamato".

Poiché l'oggetto non è ancora considerato come costruito, dopo che il costruttore ha fallito con un'eccezione, il distruttore non verrà chiamato.

L'assegnazione degli oggetti e la costruzione (solo distruzione) sono cose diverse.

Eventuali oggetti allocati usando new() prima che l'eccezione venga lanciata perderanno.

Non dovresti gestire queste risorse da solo, a meno che tu non ne abbia davvero, davvero, davvero bisogno e sia sicuro al 100% di ciò che stai facendo.

Piuttosto, utilizzare i puntatori intelligenti adatti per i membri della classe dalla libreria di gestione dinamica della memoria standard .


Quando il costruttore lancia, non verrà chiamato nessun distruttore. Quando un'eccezione viene lanciata all'interno di un costruttore, ci sono diverse cose da prendere in considerazione per gestire correttamente le allocazioni di risorse che potrebbero essersi verificate nella costruzione abortita dell'oggetto:

  • il distruttore per l'oggetto che si sta costruendo non verrà chiamato.
  • verranno chiamati distruttori per gli oggetti membri contenuti nella classe di quell'oggetto
  • la memoria per l'oggetto che si stava costruendo verrà liberata.




constructor