Interview Prep — C++ Track
C++ Interview Questions
15 C++ questions — references vs pointers, RAII, smart pointers, the rule of five, virtual functions and the vtable, and move semantics. The memory-model depth systems and quant interviewers dig into. Tagged for FAANG and startups.
CoreMemoryAdvanced
15Total
5Core
5Memory
5Advanced
Core C++
01References vs pointers — what's the difference?C++▾
| Reference | Pointer | |
|---|---|---|
| Null | Cannot be null | Can be null |
| Reassign | Bound once at init | Can point elsewhere |
| Init required | Yes | No |
| Arithmetic | No | Yes (p+1) |
| Syntax | Acts like the object | Needs * / -> |
Guidance: prefer references for function parameters that must always refer to a valid object; use pointers when the target is optional (can be null) or must be re-pointed.
02Pass by value vs reference vs const reference?C++▾
- By value — copies the argument; caller unaffected. Fine for small types (
int,double). - By reference (
T&) — no copy; the function can modify the caller's object. - By const reference (
const T&) — no copy, cannot modify. The default for large objects.
cpp
void print(const std::string& s); // no copy, read-only void sort(std::vector<int>& v); // mutates caller's vector
03What does
const correctness mean?C++▾
Using
const everywhere the data should not change — parameters, member functions, and pointers. It documents intent, lets the compiler catch accidental mutation, and enables optimizations.
cpp
int size() const; // method doesn't modify the object const int* p; // pointer to const int (can't change *p) int* const q = &x; // const pointer (can't repoint q)
Read right-to-left:
const int* p = "p is a pointer to a const int"; int* const q = "q is a const pointer to an int".04
struct vs class in C++?C++▾
The only language-level difference: members and inheritance are
public by default in a struct, and private by default in a class. Both can have constructors, methods, access specifiers, and inheritance.
Convention: use
struct for passive data aggregates (plain fields), class for types with invariants and behaviour. It's a readability signal, not a technical one.05Compile-time polymorphism vs runtime polymorphism?C++▾
- Compile-time (static) — function/operator overloading and templates. Resolved by the compiler; zero runtime cost.
- Runtime (dynamic) —
virtualfunctions dispatched through the vtable, based on the object's actual type at run time.
Memory & Resources
06Stack vs heap — how do they differ?C++▾
| Stack | Heap | |
|---|---|---|
| Allocation | Automatic (scope) | Manual (new) or smart ptr |
| Speed | Very fast (pointer bump) | Slower (allocator) |
| Size | Small, fixed | Large |
| Lifetime | Ends at scope exit | Until freed |
| Risk | Overflow (deep recursion) | Leaks, fragmentation |
Prefer the stack and RAII objects. Reach for the heap only when an object must outlive its scope or is too large for the stack.
07What is RAII?C++▾
RAII (Resource Acquisition Is Initialization) ties a resource's lifetime to an object's scope: acquire in the constructor, release in the destructor. When the object goes out of scope — even via an exception — the destructor runs and cleans up automatically.
RAII is the foundation of smart pointers, file streams, and lock guards. It's why idiomatic C++ rarely needs manual cleanup.
cpp
{
std::lock_guard<std::mutex> lk(m); // locks here
// ... critical section ...
} // unlocks automatically at scope end08Compare
unique_ptr, shared_ptr, and weak_ptr.C++▾unique_ptr— sole ownership, no overhead, move-only. The default choice.shared_ptr— shared ownership via an atomic reference count; freed when the count hits zero.weak_ptr— a non-owning observer of ashared_ptr; used to break reference cycles.
cpp
auto u = std::make_unique<Widget>(); // one owner auto s = std::make_shared<Widget>(); // ref-counted std::weak_ptr<Widget> w = s; // observes, doesn't own
Cycle trap: two
shared_ptrs pointing at each other never reach count zero — a leak. Make one direction a weak_ptr.09What is a dangling pointer, and how do you avoid one?C++▾
A dangling pointer points at memory that has been freed or gone out of scope. Dereferencing it is undefined behavior — often a silent corruption rather than a clean crash.
Avoid it by: setting freed pointers to
cpp
int* p = new int(5); delete p; *p = 10; // UB — p dangles
nullptr, never returning addresses of locals, and using smart pointers so ownership and lifetime are explicit.
10
new/delete vs malloc/free?C++▾| new / delete | malloc / free | |
|---|---|---|
| Constructors | Called | Not called (raw bytes) |
| Returns | Typed pointer | void*, needs cast |
| On failure | Throws bad_alloc | Returns NULL |
| Size | Computed automatically | You compute bytes |
new/delete, and never mix the two families (don't free a new'd pointer).
Advanced C++
11Explain the rule of three / five / zero.C++▾
- Rule of Three: if you define any of destructor, copy constructor, or copy assignment, you probably need all three (they manage a resource).
- Rule of Five: with move semantics (C++11), add the move constructor and move assignment.
- Rule of Zero: best of all — design classes so members (smart pointers, containers) manage resources, and you define none of the five.
Modern goal: aim for the rule of zero. Let
vector, string, and smart pointers handle resources so the compiler-generated special members just work.12How do virtual functions and the vtable work?C++▾
A class with
virtual functions gets a hidden vtable (array of function pointers). Each object stores a vptr to its class's vtable. A virtual call looks up the function through the vptr at runtime, so the derived override runs even through a base pointer.
cpp
Base* p = new Derived(); p->speak(); // Derived::speak via vtable dispatch
Critical: a polymorphic base class needs a
virtual destructor. Deleting a Derived through a Base* without one only runs ~Base, leaking the derived part.13What are move semantics and rvalue references?C++▾
Move semantics (C++11) let you transfer resources out of a temporary instead of copying them. An rvalue reference (
This turns an O(n) deep copy of a large container into an O(1) pointer swap.
T&&) binds to temporaries, and std::move casts an lvalue to one so its resources can be stolen.
cpp
std::vector<int> a = {1, 2, 3}; std::vector<int> b = std::move(a); // steals a's buffer, no copy // a is now valid but unspecified (usually empty)
14Shallow copy vs deep copy?C++▾
A shallow copy copies pointer members as-is, so two objects share (and both try to free) the same memory — a double-free crash. A deep copy duplicates the pointed-to data so each object owns its own.
Why it matters: the compiler-generated copy constructor does a member-wise (shallow) copy. If your class owns a raw pointer, you must write a deep-copying copy constructor and assignment (the rule of three) — or use a smart pointer / container and get the rule of zero.
15What are templates? How do they differ from Java generics?C++▾
Templates generate a separate, specialized version of a function or class for each type used, at compile time, with zero runtime overhead.
cpp
template<typename T> T maximum(T a, T b) { return a > b ? a : b; } maximum(3, 7); // stamps out int version maximum(2.5, 1.5); // stamps out double version
vs Java generics: C++ templates are reified — the type survives and each instantiation is real, optimized code. Java erases generic types at compile time, so
List<String> is just List at runtime.No questions match your search.