Decidir entre classes e structs é menos sobre sintaxe e mais sobre semântica. A escolha entre semântica por valor e por referência afeta memória, desempenho, mutabilidade e arquitetura. Este guia explica as trocas práticas e fornece regras claras para escolher o tipo certo.
November 15, 2025 (4mo ago) — last updated March 2, 2026 (1mo ago)
Classes vs Structs: How to Choose (Value vs Reference)
Compare classes e structs: descubra quando usar tipos por valor ou referência, impactos na memória e desempenho, e regras práticas de design.
← Back to blog
Classes vs Structs: When to Use Each
Resumo: Compare classes e structs—valor vs referência, memória, desempenho e orientações de design para escolher o tipo certo para código eficiente.
Introdução
Decidir entre classes e structs é menos sobre sintaxe e mais sobre semântica. A pergunta central é se você precisa de semântica por valor, onde os dados são copiados, ou semântica por referência, onde a identidade e o estado são compartilhados. Essa escolha afeta uso de memória, desempenho, mutabilidade e arquitetura. Este guia explica as trocas práticas e oferece regras claras para escolher o tipo adequado ao seu código.
A distinção central: semântica por valor vs por referência

Quando você elimina a sintaxe da linguagem, classes versus structs é uma conversa sobre tipos por valor versus tipos por referência. Pense em um struct como um bloco de notas fotocopiado: você dá suas anotações a alguém e essa pessoa recebe a própria cópia; ela pode rabiscar sem alterar seu original. Isso é semântica por valor. Uma class é como um documento compartilhado: você envia um link e todos editam o mesmo objeto. Isso é semântica por referência.
Diferenças principais em resumo
| Característica | Structs (tipos por valor) | Classes (tipos por referência) |
|---|---|---|
| Manipulação de dados | Dados são copiados quando passados | Uma referência (ponteiro) é passada |
| Alocação de memória | Frequentemente inline ou na stack | Alocado no heap |
| Ciclo de vida | Cópias efêmeras, vida curta | Instâncias compartilhadas e de vida longa |
| Identidade | Definida por igualdade de dados | Identidade distinta, independente dos dados |
| Herança | Geralmente sem herança | Suporta herança e polimorfismo |
| Uso primário | Valores pequenos e autocontidos | Entidades complexas com comportamento |
Esses princípios têm consequências práticas para latência, uso de memória e correção. Escolher deliberadamente torna o código mais previsível e fácil de manter.
Como a alocação de memória impacta o desempenho

A stack e o heap são onde a maioria dos efeitos de desempenho aparece. Alocações na stack são muito rápidas porque são apenas aritmética de ponteiro; alocações no heap são mais custosas e podem aumentar a pressão sobre o coletor de lixo em runtimes gerenciados. Em microbenchmarks, alocações no heap podem ser uma ordem de grandeza mais lentas que alocações na stack, o que torna importante evitar alocações desnecessárias em loops críticos12.
A stack: rápida e previsível
A stack é uma região LIFO onde dados locais de função são empurrados e removidos. Para tipos por valor pequenos, alocar e desalocar na stack tem custo quase nulo.
O heap: flexível, mas mais custoso
O heap permite que objetos sobrevivam além de uma chamada de função, mas a alocação é mais lenta e pode acionar coleta de lixo ou desalocação manual. Tipos por referência introduzem uma indireção: a stack contém um ponteiro para dados no heap. Alocações repetidas no heap aumentam a pressão sobre o GC e podem causar pausas em runtimes gerenciados1.
Exemplo em C#
// Value Type - lives inline (often on the stack)
public struct PointStruct {
public int X;
public int Y;
}
// Reference Type - object lives on the heap
public class PointClass {
public int X;
public int Y;
}
public void ProcessPoints() {
PointStruct p1 = new PointStruct { X = 10, Y = 20 };
PointClass p2 = new PointClass { X = 10, Y = 20 };
}
Em loops apertados, milhares de alocações no heap para objetos pequenos aumentam significativamente a atividade do GC; structs em arrays frequentemente apresentam melhor localidade de cache e menor pressão do GC2.
Como as linguagens tratam classes e structs

A melhor escolha depende tanto da linguagem quanto do domínio do problema. Abaixo, padrões comuns em linguagens populares.
C++: palavras-chave quase idênticas
Em C++, struct e class são quase iguais; a diferença técnica é o acesso padrão (público para struct, privado para class). Use struct para agregados simples e class para tipos encapsulados com comportamento complexo3.
C#: uma divisão clara entre valor e referência
C# torna a distinção explícita: struct é um tipo por valor, class é um tipo por referência. Use structs para valores pequenos e imutáveis, como coordenadas e cores, e classes para entidades com identidade ou estado compartilhado.
Swift: preferir tipos por valor
Swift incentiva valores por padrão. A comunidade Swift recomenda struct por defeito e class apenas quando for necessária semântica de referência, por exemplo para state compartilhado ou interoperabilidade com Objective-C4.
Rust: propriedade e segurança
Rust usa struct com ownership e borrowing para oferecer segurança de memória sem coletor de lixo. Comportamento é anexado via blocos impl, e o compilador aplica regras de ownership em tempo de compilação, evitando muitos bugs de estado compartilhado antes da execução5.
struct Player {
username: String,
level: u32,
is_active: bool,
}
impl Player {
fn level_up(&mut self) {
self.level += 1;
}
}
A abordagem do Rust oferece desempenho com controle direto de memória e garantias de segurança em compilação.
Quando escolher um struct para melhor desempenho
Escolha um struct quando o tipo for pequeno, autocontido e tratado como um valor em vez de uma identidade. Candidatos típicos:
- Pontos geométricos (Point2D)
- Valores de cor (RGB/RGBA)
- Pequenos payloads de configuração
- Entradas leves para cálculos
Os benefícios incluem menos alocações no heap, melhor localidade de cache e menor pressão do GC. Melhor localidade de cache pode gerar ganhos substanciais em loops que processam muitos elementos, porque padrões de acesso ficam mais amigáveis ao hardware da CPU2.
Quando escolher uma class para modelar comportamento complexo
Escolha uma class quando um objeto tem identidade estável, estado mutável compartilhado ou quando você precisa de herança e gerenciamento complexo de ciclo de vida. Candidatos típicos:
- Perfis de usuário ou entidades de domínio
- Objetos de conexão com banco de dados ou rede
- Serviços e gerentes que coordenam estado
Classes facilitam modelar relacionamentos e comportamentos complexos, especialmente em arquiteturas orientadas a objetos.
Checklist de decisão: struct vs class
| Consideração | Use struct (valor) | Use class (referência) |
|---|---|---|
| Identidade | Dados definem o valor | Objeto tem identidade única |
| Mutabilidade | Imutável ou pequeno | Estado compartilhado, mutável |
| Comportamento | Lógica simples ligada a dados | Interações e comportamento complexo |
| Ciclo de vida | Escopo local, vida curta | Vida longa, compartilhado na aplicação |
| Compartilhamento | Seguro copiar | Precisa ser compartilhado por referência |
Perguntas comuns
Um struct pode ter métodos?
Sim. Linguagens como C#, Swift e Rust permitem que structs tenham métodos, inicializadores e implementem protocolos ou interfaces. A diferença principal permanece em como são copiados e passados.
Structs são sempre mais rápidos?
Não. Structs pequenos muitas vezes são mais rápidos, mas structs grandes podem ser caros para copiar. Sempre profile a carga de trabalho real antes de migrar muitos tipos para structs.
Structs suportam herança?
Geralmente não. Structs raramente suportam herança clássica, mas muitas linguagens permitem que structs implementem interfaces ou protocolos, favorecendo composição em vez de hierarquias profundas.
Perguntas e respostas práticas
Q: Quando devo refatorar uma class para um struct?
A: Refatore quando o tipo for um valor pequeno, imutável, sem identidade única e quando você deseja reduzir alocações no heap e adotar semântica de valor.
Q: Como evito pausas de GC em linguagens gerenciadas?
A: Reduza alocações de curta duração preferindo structs para valores pequenos, reutilize objetos com pools e meça o comportamento do GC sob carga1.
Q: Qual a regra prática mais fácil?
A: Se o objeto representa “um valor”, use um struct; se representa “uma coisa com identidade”, use uma class.
Três perguntas rápidas — resumo em Q&A
Q1 — Mudar para structs sempre melhora a velocidade?
A1 — Não sempre. Use structs para valores pequenos e frequentemente criados para reduzir pressão do GC e melhorar localidade de cache; evite structs grandes que encarecem cópias.
Q2 — Structs reduzem bugs de concorrência?
A2 — Sim. Semântica por valor evita mutação compartilhada acidental, o que reduz bugs relacionados ao estado e concorrência quando valores são copiados em vez de compartilhados.
Q3 — Quando escolher class em vez de struct?
A3 — Use class quando identidade, ciclo de vida de longa duração, ou herança e polimorfismo forem necessários.
At Clean Code Guy, ajudamos equipes a refatorar para escalabilidade e manutenibilidade. Saiba mais em https://cleancodeguy.com.
IA escreve código.Você faz durar.
Na era da aceleração da IA, código limpo não é apenas uma boa prática — é a diferença entre sistemas que escalam e bases de código que entram em colapso sob seu próprio peso.