2015-11-03 13 views
6

Ho una classe con un distruttore eliminata (in pratica, ha bisogno di un aiuto esterno per essere distrutta):uso implicito del distruttore

struct indestructible { 
    indestructible(indestructible&&); 
    ~indestructible() = delete; 
}; 

Quando provo ad usare il suo costruttore mossa, il compilatore si lamenta:

struct user { 
    indestructible ind; 
    user(indestructible&& ind) : ind(std::move(ind)) {} 
}; 

indestructible.cc:11:3: error: attempt to use a deleted function 
user(indestructible&& ind) : ind(std::move(ind)) {} 
^ 
indestructible.cc:6:3: note: '~indestructible' has been explicitly marked deleted here 
    ~indestructible() = delete; 

Cosa sta succedendo? non ci sono altri membri che possono lanciare, e nemmeno il corpo del costruttore, quindi perché c'è qualche motivo per il costruttore di movimento di invocare il distruttore?

+5

Se "indistruttibile" non può essere distrutto, come può essere distrutto qualsiasi oggetto che lo contiene? –

+2

Si noti che il distruttore di 'user' tenterà ancora di distruggere' ind' – JSQuareD

+0

Una soluzione (leggermente) migliore di un distruttore eliminato potrebbe essere un distruttore privato o protetto e l'utente deve derivare o essere amico. In alternativa è possibile progettare l'oggetto in modo che possa effettivamente avere un normale distruttore e il lavoro speciale da eseguire nel costruttore invece l'utente –

risposta

3

[class.base.init]/12:

In un costruttore non delega, il distruttore per ciascun diretto o classe base virtuale e per ciascuna componente di dati non-statico del tipo classe è potenzialmente richiamato (12.4). [Nota: questa disposizione garantisce che i distruttori possano essere chiamati per oggetti secondari completamente costruiti nel caso in cui venga emessa un'eccezione (15.2). - nota end]

[class.dtor]/11:

Un programma è mal formato, se un distruttore che è potenzialmente invocato è eliminato o non è accessibile dal contesto dell'invocazione.

Non viene fatta eccezione per un costruttore che non getta. Vedi anche CWG 1915.

+0

Grazie. Sembra che sia il momento dell'unione per me. –

7

Quando l'oggetto user esce dall'ambito, viene distrutto. I suoi membri sono destrutturati, incluso il membro indestructible, e questo è impossibile dal momento che il suo distruttore viene cancellato.

+2

Nel mio esempio, l'oggetto utente non esce mai da alcun ambito. Considerare: 'utente auto = nuovo utente (std :: mossa (* nuova indistruttibile));' così 'distruttore di user' non viene mai chiamato. Considera anche il contesto del messaggio di errore del compilatore: è il costruttore di spostamenti di 'utente'. Perché deve istanziare il distruttore lì? –

+0

Poiché lo "spostamento" di un oggetto non significa che l'oggetto spostato da cessa di esistere. 'auto a = std :: move (b);' non distrugge 'b'. Spetta al programmatore implementare il costruttore di mosse in cui è indicato.Per il compilatore, la durata di 'b' termina quando' b' esce dall'ambito. – JohnB

+0

Inoltre, ': ind (std :: move (ind))' funziona sul parametro 'ind', che è una variabile e quindi esce dall'ambito alla fine del costruttore di mosse. Quindi non è necessario nemmeno distruggere un utente per incorrere in problemi. – JohnB