Ho scritto this article e ho ricevuto alcuni commenti che mi hanno confuso.È vero che una dichiarazione unique_ptr, a differenza di una dichiarazione auto_ptr, è ben definita quando il suo tipo di modello è di tipo incompleto?
Si riduce sostanzialmente verso il basso per il mio aver visto T2
utilizzato solo come un parametro di template e erroneamente saltato alla conclusione che ho potuto quindi cogliere l'occasione della dichiarazione anticipata:
struct T2;
struct T1
{
std::auto_ptr<T2> obj;
};
Questo richiama UB se I don' t andare a definire T2
da qualche parte nello stesso TU, perché std::auto_ptr<T2>
chiamate delete
sul suo interno T2*
, e calling delete
on an pointer to an object of an incomplete type whose complete type has a non-trivial destructor is undefined:
[C++11: 5.3.5/5]:
Se l'oggetto da eliminare ha un tipo di classe incompleto al punto di eliminazione e la classe completa ha un distruttore non banale o una funzione di deallocazione, il comportamento non è definito.
La toolchain GCC mi è capitato di utilizzare — v4.3.3 (Sourcery G ++ Lite 2009q1-203) — stato così gentile da farmi sapere con una nota:
nota: né il distruttore, né verrà chiamato l'operatore dell'operatore specifico della classe, anche se vengono dichiarati al momento della definizione della classe.
anche se sembra difficile ottenere questa diagnostica in altre versioni di GCC.
La mia lamentela era che sarebbe stato molto più facile da individuare un bug come questo se delete
ing un puntatore a un'istanza di un tipo incompleto sono stati mal formate piuttosto che UB, ma che sembra un problema di intractible per un'implementazione da risolvere, quindi capisco perché è UB.
Ma poi mi viene detto che, se dovessi usare std::unique_ptr<T2>
invece, questo sarebbe sicuro e conforme.
n3035 presumibilmente dice a 20.9.10.2:
Il parametro di modello
T
diunique_ptr
può essere un tipo incompleto.
Tutto quello che posso trovare in C++ 11 corretta è:
[C++11: 20.7.1.1.1]:
/1 Il modello di classe
default_delete
serve come predefinita deleter (politica distruzione) per il modello di classeunique_ptr
./2 Il parametro template
T
didefault_delete
può essere un tipo incompleto.
Ma, default_delete
s' operator()
richiede un tipo completo:
[C++11: 20.7.1.1.2/4]:
SeT
è un tipo incompleto, il programma è mal-formata.
Suppongo che la mia domanda è questa:
Sono i commentatori sul mio articolo corretto nel dire che un'unità di traduzione che consiste di solo il seguente codice è ben formata e ben definito? O hanno torto?
struct T2;
struct T1
{
std::unique_ptr<T2> obj;
};
se sono corrette, come è un compilatore prevede di implementare questo, dato che ci sono buone ragioni per questo che sono UB, almeno quando un std::auto_ptr
viene utilizzato?
Poiché la dicitura è "il programma è mal formato" (senza esplicito "e non è richiesta alcuna diagnostica") e non ad es. 'questo si traduce in un comportamento indefinito', questo * fa * significa che è necessaria una diagnostica (che può essere implementata come 'static_assert (sizeof (T)," ")'). Quindi sì, 'std :: unique_ptr' è più sicuro di 'std :: auto_ptr '. (Si noti che ciò è dovuto all'uso del default 'std :: default_delete ' deleter.) –
Volevo chiarire che 'il codice è ben formato e ben definito'/'c'è UB' aren ' gli unici due possibili risultati. (Potrebbe non essere quello che volevi trasmettere ma preferirei essere esplicito.) –