Secondo un autore esperto all'interno della comunità C ++, il codice mostrato di seguito non dovrebbe compilare. Ha torto?

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

Domanda

Secondo Herb Sutter il codice seguente non si compilerebbe. Vedi questo sito http://www.gotw.ca/gotw/066.htm Da dove ho estratto il seguente testo, per quanto riguarda function-try-blocks :

Verso un po 'di morale

Per inciso, ciò significa anche che l'unico (solo ripetizione) possibile uso per una funzione costruttore-bloccante è tradurre un'eccezione lanciata da una sotto-obiettivo di base o membro. Questo è morale n. 1. Successivamente, la morale n. 2 dice che la funzione distruttore-bloccanti sono interamente usele--

"--Ma aspetta!" Sento qualcuno che interrompe dal centro della stanza. "Non sono d'accordo con la morale n. 1. Posso pensare a un altro possibile uso per la funzione costruttore-bloccanti, vale a dire alle risorse gratuite allocate nell'elenco inizializzatore o nel corpo del costruttore!"

Scusa, no. Dopotutto, ricorda che una volta entrato nel gestore del blocco del costruttore, anche tutte le variabili locali nel corpo del costruttore sono già fuori portata e sei garantito che non esistono più oggetti di base o oggetti membri. Non puoi nemmeno fare riferimento ai loro nomi. O le parti del tuo oggetto non sono mai state costruite o quelle che sono state costruite sono già state distrutte. Quindi non puoi ripulire nulla che si basi sul riferimento a una base o membro della classe (e comunque, ecco a cosa servono la base e i distruttori dei membri, giusto?).

Supponendo che questa citazione, il seguente codice non dovrebbe compilare, come oggetto cat è già stato distrutto quando il processo si svolge nel catch clausola. Ma lo fa, almeno 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;
}
È stato utile?

Soluzione

Non credo che Herb Sutter stia in realtà dicendo che non si compilerà. Sta solo spiegando le conseguenze di ciò che lo standard ha da dire sulla situazione (15.3.10):

Fare riferimento a qualsiasi membro non statico o classe base di un oggetto nel gestore per un blocco di funzione di un costruttore o un distruttore per quell'oggetto comportamento indefinito.

Altri suggerimenti

Supponendo che questa citazione, il seguente codice non dovrebbe compilare ...

Beh, non ha detto che non si sarebbero mai compilati. Semmai, ho interpretato la citazione per significare "farlo è indefinito". Il comportamento indefinito può avere qualsiasi risultato: fino a includere la compilazione con successo e fare cose sorprendenti in seguito.

I compilatori sono diversi e ci sono anche switch che determinano quanto il compilatore sarà severo con il codice che sta compilando. Questo codice causerà certamente errori (guasti SEG, ecc.). Cerca di abilitare tutti gli interruttori del compilatore per costringerlo a trovarlo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top