Criar um novo objeto da classe C com o operador new () gera um erro aqui:
class C
{
public:
C() {}
virtual ~C() {}
void operator delete(void*) = delete;
};
int main()
{
C* c = new C;
}
com C2280: 'void C::operator delete(void *)': function was explicitly deleted
Mas quando eu substituir C() {}
com C() = default;
ou remover a linha para que compilador insere um construtor padrão (que eu acredito que tem o mesmo efeito com = default
), o código irá compilar e executar.
Quais são as diferenças entre o construtor padrão gerado pelo compilador e o construtor padrão definido pelo usuário que fazem isso acontecer?
Eu recebi alguma dica nesta postagem , mas a classe C aqui (sem construtor fornecido pelo usuário) não é trivial, pois o destruidor é virtual, certo?
Compilado com o mais recente Visual Studio, c ++ 17.
c++
delete-operator
default-constructor
yeshjho
fonte
fonte
noexcept
operator delete()
se o construtor é escrito manualmente ou gerado implicitamente. O que é consistente com minhas expectativas - como uma exceção pode ser lançada pelanew
expressão, o compilador precisa acessaroperator delete()
.noexcept
fará o código compilar, mas como ...?noexcept
como SebastianRedl mencionou, uma chamada paraoperator delete
não precisar ser incluída. Além disso, o g ++ apenas reclama se o destruidor é virtual. Caso contrário, ele sempre compila, mesmo se o construtor estiver jogando.Respostas:
new
A expressão chama o correspondenteoperator new
e, em seguida, chama o construtor. Se o construtor lançar uma exceção,new
deverá desfazer o efeito deoperator new
(para evitar vazamento de memória) chamando o correspondenteoperator delete
. Se o último for excluído, anew
expressão não poderá chamá-lo, o que resulta no compiladorerror: use of deleted function 'static void C::operator delete(void*)'
.Um
noexcept
construtor não pode lançar uma exceção; portanto, o correspondenteoperator delete
não é necessário, pois não será chamado por umanew
expressão. Umdefault
construtor de uma classe trivial também é umnoexcept
construtor. A presença de um destruidor virtual precisaoperator delete
ser não excluída porque o destruidor de exclusão escalar especial (um detalhe de implementação para permitir adelete
expressão através do ponteiro da classe base) invocaoperator delete
.Parece não ser especificado pelo padrão C ++ se o compilador deve exigir
operator delete
que não seja excluído, mesmo que não possa ser chamado pornew
expressão.gcc
, No entanto, não parece estar invocando o correspondenteoperator delete
nanew
expressão em todos, se édelete
d (postaram um relatório de bug ).fonte