Sei que essa pergunta já foi feita várias vezes, mas não consegui encontrar uma resposta para esse caso em particular.
Digamos que eu tenho uma classe trivial que não possui nenhum recurso e tem destruidor vazio e construtor padrão. Possui várias variáveis de membro com inicialização em classe; nenhum deles é const
.
Quero reinicializar e objetar essa classe sem escrever o deInit
método manualmente. É seguro fazer assim?
void A::deInit()
{
new (this)A{};
}
Não vejo nenhum problema com ele - o objeto está sempre em estado válido, this
ainda aponta para o mesmo endereço; mas é C ++, então eu quero ter certeza.
c++
placement-new
Amomum
fonte
fonte
*this = A{};
?*this = A{};
significa,this->operator=(A{});
ou seja, criar um objeto temporário e atribuí-lo a*this
, substituindo os valores de todos os membros de dados pelos valores do temporário. Como é isso que você deseja e é (na minha opinião) mais legível do que uma nova veiculação, eu iria com isso.Respostas:
Da mesma forma que a legalidade de
delete this
, a colocação de novos emthis
também é permitida até onde eu sei. Além disso, sobre sethis
ou outros ponteiros / referências pré-existentes podem ser usados posteriormente, existem algumas restrições:Os dois primeiros são satisfeitos neste exemplo, mas os dois últimos precisarão ser levados em consideração.
Em relação ao terceiro ponto, considerando que a função não é qualificada por const, deve ser bastante seguro assumir que o objeto original não é const. A falha está no lado do chamador se a constância tiver sido descartada. Em relação ao membro const / reference, acho que pode ser verificado afirmando que isso é atribuível:
Obviamente, como a atribuição é um requisito, você poderia simplesmente usar o
*this = {};
que eu esperaria produzir o mesmo programa. Um caso de uso talvez mais interessante pode ser reutilizar a memória de*this
um objeto de outro tipo (o que falharia nos requisitos de usothis
, pelo menos sem reinterpretar + lavagem).Semelhante a
delete this
, o posicionamento novo nothis
dificilmente poderia ser descrito como "seguro".fonte
delete ptr
énew T()
. O inverso denew(ptr)T{}
éptr->~T();
. stackoverflow.com/a/8918942/845092As regras que cobrem isso estão em [basic.life] / 5
e [vida básica] / 8
Como seu objeto é trivial, você não precisa se preocupar com [basic.life] / 5 e desde que atenda aos pontos de referência de [basic.life] / 8, então é seguro.
fonte