Em C++, uma classe sem membros de dados frequentemente resulta em um tamanho de instância de 1 byte. Isso ocorre porque o compilador precisa garantir que diferentes objetos tenham endereços de memória distintos, mesmo que não contenham dados. Vamos explorar como os construtores padrão se comportam nesse contexto.
Considere uma estrutura vazia:
struct EstruturaVazia {
};
int main() {
EstruturaVazia obj;
std::cout << sizeof(obj);
return 0;
}
Ao executar esse código, o tamenho impreso será 1. Ao inspecionar o código assembly gerado, nota-se que a instanciação de obj não envolve chamadas a construtores—o compilador apenas aloca espaço para o objeto.
EstruturaVazia obj;
std::cout << sizeof(obj);
; Código assembly resultante (exemplo simplificado):
; O tamanho 1 é passado diretamente para a função de saída, sem operações adicionais.
Agora, ao alocar um objeto na heap:
EstruturaVazia* ptr = new EstruturaVazia();
std::cout << sizeof(*ptr);
Novamente, o tamanho é 1. O código assembly mostra que new aloca 1 byte, mas nenhuma chamada a construtores é feita, já que a classe não define nenhum. O endereço alocado contém um valor como 0xCD (205 em decimal), que é típico de memória não inicializada em certos ambientes.
Para comparar, adicione um construtor explícito:
struct EstruturaComConstrutor {
EstruturaComConstrutor() {}
};
EstruturaComConstrutor obj2;
std::cout << sizeof(obj2);
EstruturaComConstrutor* ptr2 = new EstruturaComConstrutor();
std::cout << sizeof(*ptr2);
Agora, o código assembly revela chamadas ao construtor definido pelo usuário, tanto na alocação na stack quanto na heap. No entanto, o tamanho permanece 1 byte, pois não há membros de dados.
; Exemplo de assembly para EstruturaComConstrutor obj2:
; call para o endereço do construtor antes de usar o objeto.
Isso demonstra que, sem um construtor definido, o compilador pode não gerar um construtor padrão automaticamente. Em classes vazias, a instância ocupa 1 byte, e a alocação não envolve inicialização de membros.
Agora, adicione um membro de dados com inicialização:
struct EstruturaComDado {
int valor = 42;
};
EstruturaComDado obj3;
std::cout << sizeof(obj3);
EstruturaComDado* ptr3 = new EstruturaComDado();
std::cout << sizeof(*ptr3);
Neste caso, o tamanho aumenta para 4 bytes (tamanho de um int), e o código assemb mostra que o compilador gera um construtor para inicializar valor com 42. A chamada ao construtor ocorre tanto na stack quanto na heap.
; Código assembly para EstruturaComDado obj3:
; call para construtor que inicializa valor=42 antes de prosseguir.