C++ Interview Questions

Master your next C++ interview with our comprehensive collection of questions and expert-crafted answers. Get prepared with real scenarios that top companies ask.

Find mentors at
Airbnb
Amazon
Meta
Microsoft
Spotify
Uber

Master C++ interviews with expert guidance

Prepare for your C++ interview with proven strategies, practice questions, and personalized feedback from industry experts who've been in your shoes.

Thousands of mentors available

Flexible program structures

Free trial

Personal chats

1-on-1 calls

97% satisfaction rate

Study Mode

Choose your preferred way to study these interview questions

1. What causes memory leaks in C++ applications, and how do you typically detect and prevent them?

Memory leaks happen when allocated memory is never released, so the program loses the last way to free it. In C++, the usual causes are manual new or malloc without matching delete or free, ownership confusion across functions or classes, exception paths that skip cleanup, reference cycles with std::shared_ptr, and containers holding pointers longer than intended.

To detect them, I usually start with sanitizers like AddressSanitizer or LeakSanitizer, then use Valgrind on Linux for deeper leak reports. In production, rising memory over time is a clue. Prevention is mostly about design: - Prefer RAII, objects clean themselves up in destructors - Use std::unique_ptr by default, std::shared_ptr only for shared ownership - Avoid raw owning pointers - Keep ownership explicit in APIs - Use reviews, tests, and sanitizers in CI to catch leaks early

2. Can you walk me through your experience with C++ and the kinds of systems or applications you’ve built with it?

I’ve used C++ mostly for performance-critical backend and systems work, where control over memory, latency, and concurrency really matters. My strongest experience is with modern C++, especially C++14/17, and writing code that is efficient but still maintainable.

  • Built low-latency services handling high request volume, using STL, smart pointers, move semantics, and careful profiling.
  • Worked on multithreaded components with std::thread, mutexes, atomics, and thread-safe queue patterns.
  • Developed networking and IPC-heavy modules, focused on reliability, serialization, and clean failure handling.
  • Wrote parsers and data-processing pipelines where memory layout and allocation patterns had a big impact on throughput.
  • Spent time improving legacy C++ codebases, replacing raw ownership with RAII, tightening interfaces, and adding tests.

What I usually emphasize is balancing performance with readability, because in production C++ that tradeoff matters a lot.

3. What are the most significant differences between C and C++, and when does that distinction matter in practice?

C is a procedural systems language. C++ keeps that low-level control, but adds abstraction and stronger type modeling, so the biggest differences show up in how you design and maintain code, not just syntax.

  • C is mainly functions, structs, manual resource handling. C++ adds classes, RAII, constructors, destructors, templates, exceptions, and the STL.
  • C++ has stronger type safety, references, function overloading, namespaces, and generic programming, which usually catches more bugs at compile time.
  • Memory management differs in style: C often uses malloc/free; C++ prefers automatic lifetime and containers like std::vector, reducing leaks.
  • Compatibility matters: C is the common choice for kernels, embedded toolchains, ABIs, and FFI boundaries; C++ can be harder to expose cleanly.
  • In practice, the distinction matters most for large codebases, libraries, safety-critical maintenance, and performance with complexity, where C++ gives better structure without giving up speed.

No strings attached, free trial, fully vetted.

Try your first call for free with every mentor you're meeting. Cancel anytime, no questions asked.

Nightfall illustration

4. How would you explain RAII to a junior developer, and why is it so central to idiomatic C++?

RAII means, “tie resource lifetime to object lifetime.” A resource can be memory, a file handle, a mutex, a socket, anything that must be released. In C++, you acquire it in a constructor and release it in the destructor, so cleanup happens automatically when the object goes out of scope, even if an exception is thrown.

  • Example: std::lock_guard locks a mutex on construction, unlocks on destruction.
  • Same idea with std::unique_ptr, it owns heap memory and deletes it automatically.
  • This removes a huge class of bugs, leaks, double frees, forgotten unlocks, half-cleaned state.
  • It makes code exception-safe because stack unwinding still runs destructors.
  • Idiomatic C++ leans on scope and object ownership, not manual new/delete or paired open/close calls.

I’d tell a junior dev: if something needs cleanup, make an object own it.

5. How do const correctness and immutability improve code quality in C++ projects?

They improve correctness, readability, and optimization opportunities.

  • const makes intent explicit, readers immediately know what should not change.
  • It prevents accidental mutation, which cuts bugs, especially in large codebases and shared APIs.
  • It enables safer interfaces, for example const T& avoids copies while guaranteeing no modification.
  • It improves class design, because const member functions separate observers from mutators cleanly.
  • It helps the compiler optimize and catches mistakes at compile time, which is cheaper than runtime debugging.

Immutability goes a step further. If objects do not change after construction, reasoning about state becomes much easier, especially with concurrency. Fewer writable states usually means fewer edge cases, less defensive code, and simpler testing. In practice, I treat const as the default and only allow mutation where it is clearly necessary.

6. What is the Rule of Three, Rule of Five, and Rule of Zero, and how have these rules influenced the way you design classes?

These are C++ guidelines for resource-managing types.

  • Rule of Three: if a class needs a custom destructor, copy constructor, or copy assignment, it usually needs all three, because it owns something like heap memory or a file handle.
  • Rule of Five: in modern C++, add move constructor and move assignment too, so ownership can transfer efficiently.
  • Rule of Zero: best practice is to avoid owning raw resources directly, let members like std::string, std::vector, std::unique_ptr, and RAII wrappers handle cleanup.

In practice, Rule of Zero drives most of my design. I prefer composition with standard library types, so I usually write no special member functions at all. If a class truly owns a low-level resource, I make ownership explicit, often non-copyable with std::unique_ptr, or I implement all five carefully and define clear copy and move semantics.

7. Can you explain the difference between stack allocation and heap allocation in C++, and what tradeoffs come with each?

In C++, stack allocation means objects have automatic storage, like int x; or MyType obj;. They’re created when scope is entered and destroyed automatically when scope ends. Heap allocation means dynamic storage, usually via new, make_unique, or make_shared, and lifetime is controlled explicitly or through smart pointers.

  • Stack is fast, simple, and cache-friendly, but size is limited and lifetime is tied to scope.
  • Heap is flexible, good for large objects or shared/dynamic lifetimes, but allocation is slower.
  • Stack objects get automatic cleanup via RAII, heap objects need ownership management.
  • Heap misuse can cause leaks, fragmentation, dangling pointers, or extra indirection.
  • Prefer stack by default, use heap when lifetime or size requirements demand it.

In modern C++, if you need heap allocation, prefer std::unique_ptr or std::shared_ptr over raw new and delete.

8. What is the difference between a pointer, a reference, and a smart pointer, and when would you choose one over another?

They all let you work with an object indirectly, but they signal very different ownership and lifetime intent.

  • Pointer, T*, can be null, can be reassigned, and may or may not own the object. Use it for optional access, C APIs, arrays, or when ownership is handled elsewhere.
  • Reference, T&, is an alias to an existing object. It must refer to something valid and usually cannot be reseated. Use it for function parameters when null is not allowed.
  • Smart pointer wraps a raw pointer and manages lifetime automatically.
  • std::unique_ptr means exclusive ownership, cheapest and most common owning pointer.
  • std::shared_ptr means shared ownership, use only when multiple owners are truly needed. std::weak_ptr breaks cycles and observes without owning.

My rule of thumb: use references for non-owning required access, raw pointers for non-owning optional access, and smart pointers for ownership. Prefer unique_ptr by default.

User Check

Find your perfect mentor match

Get personalized mentor recommendations based on your goals and experience level

Start matching

9. How do std::unique_ptr, std::shared_ptr, and std::weak_ptr differ, and what problems can arise if they are misused?

They differ mainly in ownership.

  • std::unique_ptr has exclusive ownership, one pointer owns the object, cheap, deterministic, not copyable, movable.
  • std::shared_ptr has shared ownership, object is destroyed when the last owner goes away, but it adds reference counting overhead.
  • std::weak_ptr is a non-owning observer of a shared_ptr object, it does not keep the object alive, and you call lock() to get a temporary shared_ptr.

Common misuse problems:

  • Using shared_ptr everywhere can hide ownership design and hurt performance.
  • Cycles with shared_ptr, like parent and child owning each other, cause leaks because ref counts never reach zero.
  • Dereferencing a weak_ptr without checking lock() can fail because the object may already be gone.
  • Creating multiple shared_ptrs from the same raw pointer causes double delete.
  • Returning or storing raw pointers from a unique_ptr owner can create dangling references if lifetime is unclear.

10. Can you describe object lifetime in C++, including construction, destruction, and temporary objects?

Object lifetime is the period from when storage is initialized as an object to when its destructor starts, or the storage is reused. In practice, think about how the object is created, who owns it, and when cleanup happens.

  • Automatic objects, like local variables, are constructed at declaration and destroyed when scope exits, in reverse order.
  • Static objects live for the whole program, usually initialized before main and destroyed after it ends, though order across translation units can be tricky.
  • Dynamic objects, created with new, live until delete; in modern C++, prefer RAII and smart pointers.
  • Temporaries are unnamed objects, usually destroyed at the end of the full expression.
  • A temporary’s lifetime can be extended by binding it to a const T&, or in C++11+, to T&& in some contexts.
  • Construction happens base classes first, then members, then the class body; destruction is the reverse.

11. Explain lvalues, rvalues, and rvalue references in practical terms. Where have you used move semantics effectively?

Think of it as ownership and lifetimes. An lvalue has a stable identity, you can take its address and assign to it, like a named variable. An rvalue is usually a temporary, like std::string("hi") or a function return you do not keep. An rvalue reference, T&&, lets you bind to that temporary and safely steal its resources instead of copying them.

  • T& usually means "this object persists", T&& usually means "this object can be moved from"
  • Moving transfers buffers, pointers, file handles, etc., leaving the source valid but unspecified
  • I use move semantics in containers a lot, vec.push_back(std::move(bigObj)) avoids expensive deep copies
  • In APIs, I pass by value when I may need a copy, then member = std::move(arg) inside the constructor
  • I have also used it when returning large objects, relying on RVO first, move as a fallback

12. What is copy elision, and how do move semantics change performance characteristics in modern C++?

Copy elision is when the compiler skips creating a temporary and constructs the object directly in its final destination. In modern C++, this matters a lot for return-by-value and temporary objects. Since C++17, some cases are guaranteed, like return T(...), so no copy or move happens at all.

  • Before move semantics, returning large objects could mean expensive deep copies.
  • With move semantics, if elision does not happen, the compiler can often use a cheap move instead of a copy.
  • A move usually transfers ownership of resources, like pointers or buffers, without duplicating data.
  • For types like std::vector, move is typically O(1), while copy is O(n).
  • Performance today is often, "best case, no copy at all; fallback case, cheap move; worst case, deep copy."

So move semantics improve the non-elided path, while copy elision removes the path entirely.

13. What are pure virtual functions and abstract classes, and how have you used them to define interfaces?

Pure virtual functions are virtual functions declared with = 0, like virtual void draw() = 0;. They say, "derived classes must implement this." A class with at least one pure virtual function is an abstract class, which means you cannot instantiate it directly.

I use them to define interfaces and enforce a contract across implementations: - Example: IShape with draw() and area(), then Circle and Rectangle implement them. - This lets client code work with IShape* or std::unique_ptr<IShape> without caring about concrete types. - It improves extensibility, because new implementations plug in without changing callers. - In production C++, I usually give the interface a virtual destructor too, virtual ~IShape() = default;. - I’ve used this pattern for logger backends, storage providers, and hardware abstraction layers.

14. What is the difference between shallow copy and deep copy, and how can bugs emerge if this is handled poorly?

Shallow copy copies the member values as-is. If a class holds a raw pointer, both objects end up pointing to the same heap memory. Deep copy duplicates the pointed-to resource too, so each object owns its own separate copy.

  • Shallow copy is fine for plain values like int, double, std::array.
  • It becomes dangerous with owning raw pointers, file handles, sockets, mutexes.
  • Common bugs are double delete, use-after-free, dangling pointers, and accidental shared state.
  • Example: copy an object with char* data; destroying one frees data, the other now holds garbage.
  • In C++, prefer RAII types like std::string, std::vector, std::unique_ptr, or implement copy constructor and copy assignment correctly, rule of three/five.

If ownership is unclear, copies become a time bomb. Modern C++ avoids most of this by not manually owning memory unless necessary.

15. When would you use inheritance versus composition in C++, and why?

I default to composition, and use inheritance when I truly need substitutability.

  • Use inheritance for an is-a relationship, where derived objects must work anywhere the base is expected, following Liskov substitution.
  • Good fit: shared interface plus polymorphism, like Shape with virtual draw(), and Circle, Rectangle implementations.
  • Use composition for a has-a or uses-a relationship, like Car containing an Engine or a Logger.
  • Composition is usually safer, it keeps coupling lower, avoids fragile base class problems, and lets you swap behavior more easily.
  • Inheritance exposes implementation decisions into the type hierarchy, composition hides them and is more flexible for change.

So, inheritance for stable abstractions and polymorphic APIs, composition for reuse and evolving designs.

16. Can you explain object slicing and how to avoid it?

Object slicing happens when you copy a derived object into a base object by value. The base part gets copied, but the derived-specific fields and behavior are sliced off. For example, if Derived inherits Base, then Base b = derived; loses the Derived part. Also, virtual dispatch will not save you if the object itself was sliced.

To avoid it: - Prefer references or pointers, like Base& or Base*, when working polymorphically. - Use smart pointers such as std::unique_ptr<Base> or std::shared_ptr<Base> for ownership. - Avoid pass-by-value for base classes in APIs, use const Base& instead. - If copying polymorphic objects is needed, use a virtual clone() that returns std::unique_ptr<Base>. - Consider deleting base copy operations if value-copying would be dangerous.

17. What are virtual functions, and how does dynamic dispatch work under the hood at a high level?

Virtual functions let you call behavior through a base class interface and still get the derived class implementation at runtime. That is the core of runtime polymorphism in C++.

  • Mark a base member virtual, then overriding it in a derived class makes calls resolve by the object’s dynamic type, not the pointer or reference type.
  • Example: Base* p = new Derived; p->f(); calls Derived::f() if f is virtual.
  • Under the hood, most compilers add a hidden pointer in polymorphic objects, often called a vptr.
  • That vptr points to a virtual table, or vtable, which stores function addresses for that class’s virtual functions.
  • On a virtual call, the program follows the object’s vptr, looks up the right slot in the vtable, and jumps to that function.

It costs a small indirection, but enables flexible interfaces. Constructors do not dispatch to more-derived overrides.

Get Interview Coaching from C++ Experts

Knowing the questions is just the start. Work with experienced professionals who can help you perfect your answers, improve your presentation, and boost your confidence.

Complete your C++ interview preparation

Comprehensive support to help you succeed at every stage of your interview journey

Still not convinced? Don't just take our word for it

We've already delivered 1-on-1 mentorship to thousands of students, professionals, managers and executives. Even better, they've left an average rating of 4.9 out of 5 for our mentors.

Find C++ Interview Coaches