Pergunta

Esta questão já tem uma resposta aqui:

Em meus testes básicos iniciais é perfeitamente seguro fazê-lo. No entanto, tem-me que tentar manipular this mais tarde, em uma função que deletes this poderia ser um erro de execução. Isso é verdade, e é normalmente seguro para delete this? ou existem apenas alguns casos em que é seguro?

Foi útil?

Solução

delete this é legal e faz o que você esperaria: chama destruidor de sua classe e liberar a memória subjacente. Depois delete this retornos, o valor do ponteiro this não mudança, por isso é agora um apontador pendente que deve não ser dereferenced. Isso inclui dereferencing implícita usando variáveis ??membro da classe.

Ele é normalmente encontrado nas classes contou-referência que, quando o ref-contagem é diminuída para 0, o DecrementRefCount() / Release() / whatever membro função chama delete this.

delete this é normalmente considerado uma forma muito ruim para muitas razões. É fácil de variáveis ??de membro acidentalmente Access depois delete this. código chamador pode não perceber o seu objeto tem auto-destruiu.

Além disso, delete this é um "cheiro de código" que seu código pode não ter uma estratégia simétrica para a posse do objeto (quem aloca e quem apaga). Um objeto não poderia ter alocado-se com new, assim que chamar meios delete this que a classe A está alocando um objeto, mas a classe B é mais tarde liberando-[auto].

Outras dicas

É seguro excluir "isto", enquanto ele é essencialmente a última operação no método. Na verdade várias APIs de nível profissional fazê-lo (ver implementação CComObject de ATL para um exemplo).

O único perigo está tentando acessar quaisquer outros dados de membros depois de chamar "excluir este". Este é certamente inseguro.

Apagar esta é perfeitamente legal como outros já mencionados. É arriscado, por uma razão adicional que ainda não foi mencionado - você está assumindo que o objeto foi alocado no heap. Isso pode ser difícil de garantia, embora no caso de implementações de contagem de referência, geralmente não é um problema.

Mas não fazê-lo no processo de destruição!

Como dito por outros, excluir esta é uma expressão válida, mas para que ele seja seguro você tem que garantir que o objeto nunca é instanciado na pilha.

Uma maneira de fazer isso é fazer com que tanto o construtor eo destruidor privado e reforçar a criação do objeto através de uma função de fábrica de classe que cria o objeto na pilha e retorna um ponteiro para ele. A fábrica de classe pode ser uma função membro estático ou uma função amigo. Limpeza pode ser feito através de um método Delete () sobre o objeto que faz o "excluir este". COM objetos basicamente trabalhar desta forma, exceto que, além disso, são referência contou com a "excluir este" ocorre quando a contagem de referência é diminuída a zero.

Sim. Deve ser perfeitamente bem. "Isto" é apenas um ponteiro. Qualquer ponteiro vai fazer por exclusão. As informações sobre como excluir um objeto está contido nos registros da pilha. Isto é como IUnknown :: Release () é normalmente implementado em COM objetos.

apagar isso pode causar um problema quando você tem subclasses do objeto que você está excluindo. Lembre-se de construção começa a partir de cima para baixo e de exclusão começa a partir-se inferior. Então, se eliminar este está no meio da hierarquia você basicamente perdeu todos os objetos abaixo desta classe particular.

excluir este é muito útil quando você está implementando uma referência contados objeto, um exemplo de que é as classes COM.

Leia para uma discussão semelhante. Seu entendimento é direito na medida em que não trabalho, é necessário, e pode ser perigoso desde que você não pode acessar esta tarde.

Sim Legal
Seguro Nenhum

Se você está herdando de uma classe base e deu excluir esta na função de classe base, usando ponteiro classe derivada irá causar um acidente. Por exemplo:

class Base
{

    virtual void Release()
    {
        delete this;
    }

}

class Derived : public Base
{

    void Foo()
    {
        ...
    }

}

main()
{

    Base *ptrDerived = new Derived();
    ptrDerived->release();
    ptrDerived->Foo() //Crash

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top