Vamos supor que eu tenha o seguinte código ( https://godbolt.org/z/MW4ETf7a8 ):
Xh
#include <iostream>
struct X{
void* operator new(std::size_t size)
{
std::cout << "new X\n";
return malloc(size);
}
void operator delete(void* ptr)
{
std::cout << "delete X\n";
return free(ptr);
}
virtual ~X() = default;
};
struct ArenaAllocatedX : public X {
void* operator new(std::size_t size)
{
std::cout << "new ArenaAllocatedX\n";
return malloc(size);
}
void operator delete(void* ptr)
{
std::cout << "delete ArenaAllocatedX\n";
return free(ptr);
}
};
principal.cpp
int main() {
X* x1 = new X();
delete x1;
X* x2 = new ArenaAllocatedX ();
delete x2;
}
Usando o GCC 10.3.1,
x1
chama os operadores new
e de , enquanto chama de .delete
class X
x2
class ArenaAllocatedX
Eu entendo como ele pegará o new
operador, já que ele tem o nome real da classe à sua direita, mas não entendo como o delete
operador é escolhido para a subclasse enquanto é apontado por X*
.
Os operadores new
/ são delete
considerados funções dentro da tabela virtual (descartei o VTable usando gcc -f-dump-lang-class
e ainda não vejo nenhum operador de exclusão)?
Os despejos do VTable:
Vtable for X
X::_ZTV1X: 4 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI1X)
16 (int (*)(...))X::~X
24 (int (*)(...))X::~X
Class X
size=8 align=8
base size=8 base align=8
X (0x0x7f38cd807780) 0 nearly-empty
vptr=((& X::_ZTV1X) + 16)
Vtable for ArenaAllocatedX
ArenaAllocatedX::_ZTV15ArenaAllocatedX: 4 entries
0 (int (*)(...))0
8 (int (*)(...))(& _ZTI15ArenaAllocatedX)
16 (int (*)(...))ArenaAllocatedX::~ArenaAllocatedX
24 (int (*)(...))ArenaAllocatedX::~ArenaAllocatedX
Class ArenaAllocatedX
size=8 align=8
base size=8 base align=8
ArenaAllocatedX (0x0x7f38cd848680) 0 nearly-empty
vptr=((& ArenaAllocatedX::_ZTV15ArenaAllocatedX) + 16)
X (0x0x7f38cd807cc0) 0 nearly-empty
primary-for ArenaAllocatedX (0x0x7f38cd848680)
Como o C++ escolhe qual delete
operador usar no código fornecido?