Pergunta

Como isso é possível que ele é permitido objeto de exclusão com destructor privada no código a seguir? Eu reduzi programa real para o exemplo a seguir, mas ainda compila e obras.

class SomeClass;

int main(int argc, char *argv[])
{
  SomeClass* boo = 0; // in real program it will be valid pointer
  delete boo; // how it can work?

  return -1;
}

class SomeClass
{
private:
  ~SomeClass() {}; // ! private destructor !
};
Foi útil?

Solução

Você está tentando excluir objeto do tipo classe incompleta. C ++ Padrão diz que você vai ter um comportamento indefinido, neste caso (5.3.5 / 5):

Se o objecto a ser suprimida tem tipo de classe incompleta no ponto de eliminação e a classe completa tem um destruidor não trivial ou uma função desatribuição, o comportamento é indefinido.

Para detectar tais casos, você pode usar boost::checked_delete :

template<typename T> 
inline void checked_delete( T* p )
{
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
    (void) sizeof(type_must_be_complete);
    delete p;
}

Outras dicas

Este código provoca um comportamento indefinido (UB). É UB em C ++ para delete um objecto do tipo incompleto tendo um destruidor não trivial. E em seu código do tipo SomeClass é incompleta no ponto de delete, e tem um destrutor não-trivial. Compiladores normalmente emitir um aviso sobre isso, já que em C ++ formalmente esta não é uma violação de restrição.

Assim, estritamente falando, seu código não faz "trabalho". Ele simplesmente compila e faz algo indefinido quando for executado.

O compilador não é apenas necessário para pegar esse erro. A razão para isto é que este poderia ser perfeitamente bem se o seu objeto tem um trivial destructor. O compilador não tem como saber que tipo de destruidor este tipo acabará por ter, por isso não posso dizer com certeza se este é um erro ou não.

Como o tipo SomeClass não está completamente declarou ao invocar operator delete.

A exclusão de tal ponteiro é um comportamento indefinido, mas na prática a maioria dos compiladores só iria liberar a memória (se o ponteiro foi não-NULL) e não chamar o destruidor.

Por exemplo, g ++ vai lhe dar um aviso sobre esse problema:

foo.cpp: In function 'int main(int, char**)':
foo.cpp:6: warning: possible problem detected in invocation of delete operator:
foo.cpp:5: warning: 'boo' has incomplete type
foo.cpp:1: warning: forward declaration of 'struct SomeClass'
foo.cpp:6: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top