P
prepair.app
Começar entrevista →
EnglishУкраїнськаРусскийDeutsch
🔷

Perguntas de entrevista C++

As entrevistas de C++ avaliam três coisas: se você entende o modelo de objetos, se pode ser confiável no gerenciamento de memória, e se sabe o que a biblioteca padrão realmente custa. Aqui estão as perguntas mais frequentes, cada uma com uma resposta modelo.

Junior · sem experiência / menos de 1 anoMiddle · 2–4 anos de experiênciaSenior · 5+ anos de experiência

O que perguntam

Memória, ponteiros e RAII
OOP, funções virtuais e vtable
Move semantics e a regra dos cinco
Templates e metaprogramação
Contêineres STL e complexidade
Concorrência e data races

10 perguntas reais com respostas

Cada pergunta vem com uma resposta modelo para você comparar com a sua.

1

Qual é a diferença entre um ponteiro e uma referência?

Resposta

Uma referência precisa ser vinculada na criação e nunca pode ser revinculada; um ponteiro pode ser null, reatribuído, e tem seu próprio endereço e aritmética. Na prática você usa uma referência quando a coisa precisa existir e um ponteiro quando a ausência é um estado válido. Uma referência não é um objeto separado, por isso não existem referências a referências nem arrays delas.

2

O que é RAII?

Resposta

Resource acquisition is initialization: um recurso pertence a um objeto, é adquirido no construtor dele e liberado no destrutor. Como os destrutores rodam em todo caminho de saída — incluindo uma exceção desenrolando a stack — o recurso não pode vazar por causa de um return antecipado que alguém adicionou depois. Todo smart pointer, lock guard e file stream da biblioteca padrão é essa mesma ideia.

3

`unique_ptr`, `shared_ptr`, `weak_ptr` — quando cada um se aplica?

Resposta

unique_ptr é posse exclusiva, se move mas não se copia, e não custa nada além de um ponteiro cru — deveria ser o padrão. shared_ptr é posse compartilhada com um contador de referências atômico, que não é de graça e ao qual muitas vezes se recorre quando a posse simplesmente não foi decidida. weak_ptr observa um shared_ptr sem possuí-lo, e sua principal função é quebrar ciclos de referência que de outra forma nunca seriam liberados.

4

Por que uma classe base precisa de um destrutor virtual?

Resposta

Porque deletar um objeto derivado através de um ponteiro base sem um destrutor virtual é comportamento indefinido — na prática o destrutor derivado nunca roda e seus membros vazam. A regra é: se uma classe é feita para ser herdada e deletada polimorficamente, seu destrutor é virtual. Se não é feita para ser base, ela não precisa disso, e adicioná-lo dá a ela uma vtable que não tinha.

5

O que são `vptr` e `vtable`?

Resposta

Uma classe com funções virtuais ganha uma tabela de ponteiros de função — a vtable — uma por classe, e cada objeto dela guarda um ponteiro oculto para essa tabela, o vptr. Uma chamada virtual lê o vptr, indexa a tabela, e salta. Isso é o que torna o objeto maior em um ponteiro e a chamada indireta, e por isso o compilador só consegue desvirtualizar quando consegue provar o tipo dinâmico.

6

Qual é a diferença entre a stack e a heap?

Resposta

A stack é alocada e liberada movendo um ponteiro ao entrar e sair de escopos, então é rápida, contígua e amigável ao cache, mas limitada e presa ao tempo de vida do escopo. A heap é alocada sob demanda, não tem regras próprias de tempo de vida, e custa uma chamada real ao allocator mais o risco de fragmentação. Prefira a stack; vá para a heap quando o tamanho é desconhecido ou o objeto precisa sobreviver ao escopo.

7

O que é move semantics e o que `std::move` faz?

Resposta

Move semantics permite transferir um recurso em vez de copiá-lo — o construtor de movimento de um vector rouba o ponteiro do buffer em vez de alocar e copiar elementos. std::move em si não move nada: é um cast para uma referência rvalue que torna o objeto elegível para um move. Se algo realmente se move depende de o tipo ter um construtor de movimento, e o objeto de onde se moveu fica válido mas não especificado.

8

O que é comportamento indefinido e por que é perigoso?

Resposta

Comportamento sobre o qual o padrão não impõe requisitos — ler além do fim de um array, desreferenciar null, overflow com sinal, usar incorretamente um objeto movido, um data race. É perigoso justamente porque muitas vezes parece funcionar: o compilador pode assumir que nunca acontece e otimizar sob essa suposição, então o mesmo código quebra depois de uma mudança não relacionada ou de um nível de otimização diferente. Sanitizers são como se encontra isso.

9

Quando você escolheria `std::vector` em vez de `std::list`?

Resposta

Quase sempre. vector é contíguo, então a iteração é amigável ao cache e prefetchável, enquanto list persegue um ponteiro por elemento e paga uma alocação por nó. list só vence quando você faz splice ou insere no meio constantemente e precisa manter iteradores válidos — e mesmo assim vale medir, porque em hardware moderno a localidade geralmente vence a melhor classe de complexidade.

10

O que é um data race e como evitá-lo?

Resposta

Duas threads acessando o mesmo local de memória, pelo menos uma escrevendo, sem sincronização entre elas — isso é comportamento indefinido, não apenas um resultado errado. Evita-se não compartilhando estado mutável, ou protegendo-o com um mutex, ou tornando o acesso atômico. ThreadSanitizer encontra a maioria, o que é mais confiável do que raciocinar sobre um escalonamento que você não consegue reproduzir.

🦎

Só ler as respostas não basta

Numa entrevista de verdade você fala sob pressão. O Cam faz essas mesmas perguntas, avalia cada resposta e mostra exatamente o que melhorar.

Praticar entrevista de C++ →
Grátis · 3 entrevistas por mês

Vale a pena ler

Todos os artigos →

Outras especializações

🔍QA Manual🤖QA AutomationJava Backend🐍Python Backend🐘PHP Backend🦫Go Backend🟢Node.js Backend💎Ruby on Rails🟨JavaScript⚛️React Frontend💚Vue Frontend🅰️Angular FrontendNext.js🍏iOS (Swift)🟩Android (Kotlin)⚙️DevOps / SRE🗄️Data Engineer📈Business Analyst🎯Product Manager📋Project Manager🎨UI/UX Designer📣Marketing