Função operator delete
A memória que é atribuída dinamicamente usando o operador new pode ser liberada usando o operador delete. O operador delete chama a função operator delete, que libera memória no pool disponível. Usar o operador delete também faz com que o destruidor da classe (se houver) seja chamado.
Há funções operator delete de escopo global e de classe. Apenas uma função operator delete pode ser definida para uma classe específica; se definida, oculta a função operator delete global. A função operator delete global sempre é chamada para matrizes de qualquer tipo.
A função operator delete global, se declarada, usa um argumento do tipo void *, que contém um ponteiro para o objeto a ser desalocado. O tipo de retorno é void (operator delete não pode retornar um valor). Existem duas formas para funções operator delete de membro de classe:
void operator delete( void * );
void operator delete( void *, size_t );
Somente uma das duas variantes de precedência pode estar presente para uma determinada classe. A primeira forma funciona conforme descrito para operator delete global. A segunda forma usa dois argumentos, o primeiro deles é um ponteiro para o bloco de memória a ser desalocado e o segundo é o número de bytes a ser desalocado. A segunda forma é particularmente útil quando uma função operator delete de uma classe base é usada para excluir um objeto de uma classe derivada.
A função operator delete é estática; portanto, não pode ser virtual. A função operator delete obedece o controle de acesso, conforme descrito em Controle de acesso de membros.
O exemplo a seguir mostra as funções operator new e operator delete definidas pelo usuário criadas para registrar alocações e desalocações de memória em log:
Exemplo
// spec1_the_operator_delete_function1.cpp
// compile with: /EHsc
// arguments: 3
#include <iostream>
using namespace std;
int fLogMemory = 0; // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0; // Count of blocks allocated.
// User-defined operator new.
void *operator new( size_t stAllocateBlock ) {
static int fInOpNew = 0; // Guard flag.
if ( fLogMemory && !fInOpNew ) {
fInOpNew = 1;
clog << "Memory block " << ++cBlocksAllocated
<< " allocated for " << stAllocateBlock
<< " bytes\n";
fInOpNew = 0;
}
return malloc( stAllocateBlock );
}
// User-defined operator delete.
void operator delete( void *pvMem ) {
static int fInOpDelete = 0; // Guard flag.
if ( fLogMemory && !fInOpDelete ) {
fInOpDelete = 1;
clog << "Memory block " << cBlocksAllocated--
<< " deallocated\n";
fInOpDelete = 0;
}
free( pvMem );
}
int main( int argc, char *argv[] ) {
fLogMemory = 1; // Turn logging on
if( argc > 1 )
for( int i = 0; i < atoi( argv[1] ); ++i ) {
char *pMem = new char[10];
delete[] pMem;
}
fLogMemory = 0; // Turn logging off.
return cBlocksAllocated;
}
A partir do Visual C++ 5.0, o compilador oferece suporte aos operadores new e delete da matriz de membros em uma declaração de classe. Por exemplo:
// spec1_the_operator_delete_function2.cpp
// compile with: /c
class X {
public:
void * operator new[] (size_t) {
return 0;
}
void operator delete[] (void*) {}
};
void f() {
X *pX = new X[5];
delete [] pX;
}
Comment
O código anterior pode ser usado para detectar "vazamento de memória” – ou seja, a memória atribuída no repositório livre, mas nunca liberada. Para executar essa detecção, os operadores new e delete globais são redefinidos para contar a alocação e a desalocação de memória.