Como passar em uma entrevista de C++: principais perguntas de nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Como passar em uma entrevista de C++: principais perguntas de nível avançado



Uma entrevista para a posição de desenvolvedor C++ é sempre um desafio. Se você provavelmente conhece as perguntas básicas (diferença entre new e malloc, o que é um destrutor virtual), o nível avançado exige uma compreensão profunda do funcionamento interno da linguagem. Neste artigo, analisaremos os tópicos principais que certamente surgirão em uma entrevista técnica para posições de Middle e Senior. Não apenas listaremos as perguntas, mas também daremos respostas detalhadas com exemplos de código.



1. Ponteiros inteligentes e seu funcionamento interno



Pergunta: "Explique a diferença entre std::unique_ptr e std::shared_ptr? Como a segurança de thread do contador de referências é implementada?"



Isso é um clássico. O entrevistador quer ver se você entende não apenas a sintaxe, mas também a semântica de posse de recursos.



  • std::unique_ptr — posse exclusiva. Não é copiado, apenas movido. Ideal para recursos que têm um único dono.
  • std::shared_ptr — posse compartilhada. Usa um contador de referências (control block). Quando o contador chega a zero, o recurso é destruído.
  • std::weak_ptr — "observador". Não incrementa o contador de referências. Usado para quebrar dependências cíclicas em shared_ptr.


Detalhe avançado: O contador de referências em shared_ptr é seguro para threads (usa operações atômicas), mas isso não torna o objeto gerenciado em si seguro para threads. Existem também dois contadores: de referências fortes (strong) e de referências fracas (weak). Enquanto houver pelo menos uma referência fraca, o control block não é removido, mesmo que o objeto já tenha sido destruído.



#include <memory>#include <iostream>

class Resource {public: Resource() { std::cout << "Resource acquired"; } ~Resource() { std::cout << "Resource destroyed"; } void doWork() { std::cout << "Working..."; }};

int main() { std::unique_ptr<Resource> uptr = std::make_unique<Resource>(); uptr->doWork(); // std::unique_ptr<Resource> uptr2 = uptr; // Erro de compilação! std::unique_ptr<Resource> uptr2 = std::move(uptr); // Ok

std::shared_ptr<Resource> sptr1 = std::make_shared<Resource>(); std::shared_ptr<Resource> sptr2 = sptr1; // Contador de referências = 2 sptr1.reset(); // Contador = 1 sptr2.reset(); // Contador = 0, objeto destruído return 0;}


2. Tabelas virtuais (vtable) e o mecanismo de ligação tardia



Pergunta: "Como uma função virtual funciona no nível de memória? Onde a vtable é armazenada?"



Esta pergunta testa a compreensão não apenas do polimorfismo, mas também da organização da memória em C++.



  • Para cada classe que possui pelo menos uma função virtual, o compilador cria uma tabela estática (vtable). Ela contém ponteiros para as funções virtuais.
  • Cada objeto dessa classe contém um ponteiro oculto __vptr, que aponta para a vtable de sua classe.
  • Ao chamar uma função virtual através de um ponteiro ou referência, o compilador gera código que percorre o __vptr até a vtable, encontra a função desejada pelo deslocamento e a chama.
  • A vtable é armazenada na memória estática (como uma variável global), não na pilha ou no heap.


Detalhe avançado: Complexidades com herança múltipla. Neste caso, um objeto pode ter vários __vptr, e surge a necessidade de funções thunk (ajuste do ponteiro this). Esta é uma das razões pelas quais a herança múltipla em C++ é considerada perigosa e lenta.



#include <iostream>

class Base {public: virtual void foo() { std::cout << "Base::foo"; } virtual ~Base() = def

Blogs

Book Recommendations