Cómo aprobar una entrevista de C++: principales preguntas con ejemplos de código
La entrevista de C++ es una de las pruebas más difíciles para un desarrollador. Este lenguaje combina el poder de la programación de bajo nivel con paradigmas modernos de POO y plantillas. Para superar con éxito la entrevista, no solo necesitas conocer la sintaxis, sino también entender cómo funcionan la memoria, el compilador y la biblioteca estándar. En este artículo, analizaremos las 10 preguntas principales que más se hacen en las entrevistas de C++, con respuestas detalladas y ejemplos de código.
1. ¿Qué es RAII y para qué sirve?
RAII (Resource Acquisition Is Initialization) es una de las expresiones idiomáticas clave de C++. La idea es simple: un recurso (memoria, archivo, mutex) se adquiere en el constructor del objeto y se libera en el destructor. Esto garantiza una limpieza correcta incluso en caso de excepciones.
Ejemplo de código incorrecto (sin RAII):
void process() { int* ptr = new int(42); // ... código que puede lanzar una excepción delete ptr; // fuga si la excepción ocurrió antes de delete}Ejemplo con RAII (usamos std::unique_ptr):
#include <memory>
void process() { std::unique_ptr<int> ptr = std::make_unique<int>(42); // ... código con excepciones // ptr se eliminará automáticamente al salir del ámbito}Por qué lo preguntan: RAII es la base de la gestión segura de recursos en C++. Sin él, es imposible escribir código fiable.
2. ¿Cuál es la diferencia entre una función virtual y una virtual pura?
Una función virtual (virtual) puede ser sobrescrita en una clase derivada, pero tiene una implementación en la clase base. Una función virtual pura (= 0) no tiene implementación en la clase base y hace que la clase sea abstracta: no se puede crear un objeto de dicha clase.
Ejemplo:
class Base {public: virtual void foo() { std::cout << "Base foo"; } // virtual virtual void bar() = 0; // virtual pura};
class Derived : public Base {public: void foo() override { std::cout << "Derived foo"; } void bar() override { std::cout << "Derived bar"; }};Pregunta adicional: ¿Cómo funciona vtable? El compilador crea una tabla de funciones virtuales para cada clase con métodos virtuales. Cada objeto contiene un puntero a esta tabla (vptr). Al llamar a una función virtual, se produce una despacho dinámico a través de vtable.
3. ¿Qué punteros inteligentes hay en C++ y cuándo usarlos?
En C++11 aparecieron tres tipos de punteros inteligentes:
- std::unique_ptr — propiedad exclusiva. No se puede copiar, solo mover. Ideal para recursos con un solo propietario.
- std::shared_ptr — propiedad compartida. Utiliza un contador de referencias. Adecuado cuando varios objetos deben poseer un mismo recurso.
- std::weak_ptr — no posee el recurso, pero puede observar a shared_ptr. Necesario para romper referencias cíclicas.
Ejemplo de uso de unique_ptr:
#include <memory>
class MyClass { /* ... */ };
void example() { auto ptr = std::make_unique<MyClass>(); // auto ptr2 = ptr; // ¡Error! No se puede copiar auto ptr3 = std::move(ptr); // OK, movimiento}Ejemplo de shared_ptr y weak_ptr para prevenir referencias cíclicas:
struct Node { std::shared_ptr<Node> next; std::weak_ptr<Node> prev; // weak_ptr para evitar el ciclo};4. ¿Qué es la semántica de movimiento y std::move?
La semántica de movimiento permite «mover» recursos de un objeto a otro en lugar de copiarlos. Esto es especialmente útil para objetos temporales o cuando la copia es costosa (por ejemplo, std::string o