2015-05-20 12 views
10

Supponiamo di voler chiamare una funzione esterna dell'oggetto per eseguire alcuni controlli all'interno del costruttore del corpo. Poiché la vita di un oggetto inizia quando il corpo del costruttore termina la sua esecuzione, si tratta di un design non sicuro?C++: durata di un oggetto e funzioni esterne

struct A; 

void check(A const&) { /* */ } 

struct A 
{ 
    A() { check(*this); } 
}; 

Voglio dire, sto chiamando e funzione esterna con un oggetto non ancora vivo. È un comportamento indefinito?

Domande correlate: se metto quella funzione il controllo come una funzione di membro (statico o no), che cosa lo standard dice sull'utilizzo di oggetti non-ancora-vivi al di fuori del costruttore, ma all'interno della classe?

C'è qualche differenza nel concetto di durata tra il punto di vista di una classe e i suoi utenti (una specie di vita in classe rispetto alla classe esterna)?

+2

Le [domande frequenti su C++] (https://isocpp.org/wiki/faq/ctors#using-this-in-ctors) contengono informazioni a riguardo. –

+0

Va bene finché la funzione non è un membro virtuale e non è nell'elenco di inizializzazione – KABoissonneault

+1

Un const è un riferimento e non viene inizializzato all'inizio del controllo né distrutto alla fine delle funzioni. Inoltre all'interno del costruttore l'oggetto è completamente costruito. Non vedo alcun problema in questo codice – Brahim

risposta

8

La durata di A non avrà iniziato quando check() si chiama perché, da [base.life]:

La durata di un oggetto di tipo T inizia quando:

  • storage con si ottiene l'allineamento e le dimensioni corrette per il tipo T e
  • se l'oggetto ha un'inizializzazione non vuota, la sua inizializzazione è completa.

A ha inizializzazione non vuota. La sua inizializzazione è completa quando, dal [class.base.init]/13:

In un costruttore non delega, procede inizializzazione nel seguente ordine:

  • ...
  • - Infine, viene eseguita l'istruzione composta del corpo del costruttore.

Tuttavia, nonostante A non essendo la sua vita è ancora iniziato, lo standard prevede inoltre, in [class.base.init]/16:

funzioni membri (comprese le funzioni membro virtuali, 10.3) può essere chiamato per un oggetto in costruzione ... Tuttavia, se queste operazioni vengono eseguite in un ctor-inizializzatore (o in una funzione chiamata direttamente o indirettamente da un ctor-inizializzatore) prima che tutti i mem- initi alizers per le classi base completate, il risultato dell'operazione non è definito.

Per quanto riguarda i problemi di durata, non c'è alcuna differenza tra:

void check(const A&) { .. } 
struct A { 
    A() { check(*this); } 
}; 

E:

struct A { 
    void check() const { .. } 
    A() { check(); } 
}; 

Quest'ultimo è esplicitamente consentito (in quanto non è in un ctor-initializer), quindi non vedo alcun motivo per escludere il primo per motivi di vita.

+0

... eccetto se A è una classe base con membri virtuali che vengono chiamati da 'check()' - allora i risultati potrebbero sorprendervi. –

+0

@RichardHodges Non è tuttavia un comportamento indefinito. – Barry

+0

@Barry Sei sicuro che l'inizializzazione finisce qui? http://stackoverflow.com/a/20409911/1794803 –