Talk Is Cheap, Show Me The Code
Codekilla
CODEKILLA
C++

C++ Interview Questions and Answers (Modern C++)

Top C++ interview questions — RAII, move semantics, smart pointers, templates, STL, modern C++17/20/23 features — with model answers.

← Interview Questions

C++ vs C and Basics

1. Key differences between C and C++?

C++ adds: classes & objects, templates, exceptions, namespaces, references, function overloading, the STL, RAII, smart pointers, and lambda expressions. C++ is mostly a superset of C (with some incompatibilities).

2. Pass by value vs reference vs pointer?

cpp
void byValue(int x);          // copy; safe but slow for large types
void byRef(int& x);           // alias; no copy; can modify caller's var
void byConstRef(const T& x);  // no copy; read-only — modern default for large types
void byPointer(int* x);       // explicit; nullable

3. Reference vs pointer?

ReferencePointer
Nullable❌✅
Reseatable❌✅
Syntaxx.fieldp->field
Init required✅ at decl❌

RAII and Memory

4. What is RAII?

Resource Acquisition Is Initialization. Resources (memory, file handles, locks) are tied to object lifetime — acquired in the constructor, released in the destructor. Eliminates entire categories of leaks.

5. unique_ptr vs shared_ptr vs weak_ptr?

  • unique_ptr<T> — sole owner; non-copyable, movable. Default choice.
  • shared_ptr<T> — reference-counted shared ownership. Use only when ownership is genuinely shared.
  • weak_ptr<T> — non-owning observer of a shared_ptr. Used to break reference cycles.

6. When should you use raw pointers in modern C++?

  • Non-owning references to objects whose lifetime is managed elsewhere.
  • Inside library internals where ownership is clear.
  • Almost never for owning. Use unique_ptr / shared_ptr / make_unique instead.

Move Semantics

7. What is std::move?

A cast that converts an lvalue to an rvalue, enabling move construction / move assignment to steal resources instead of copy.

cpp
std::vector<int> v1 = {1,2,3};
std::vector<int> v2 = std::move(v1);   // O(1) move, no element copy
// v1 is now in a valid-but-unspecified state — assign to it before reading

8. Rule of zero / three / five?

  • Rule of zero — let the compiler generate all special members. Prefer this. Use RAII members so you don't need any custom ones.
  • Rule of three — if you write one of {copy ctor, copy assign, dtor}, write all three.
  • Rule of five — same, but with move ctor + move assign too in modern C++.

9. std::forward vs std::move?

Both are casts. std::move always casts to rvalue. std::forward<T> preserves the value category (lvalue / rvalue) of its template argument — used in perfect forwarding inside templates.

STL

10. vector vs array vs deque?

  • std::vector<T> — dynamic array; contiguous; O(1) random access; O(1) amortised push_back; O(n) front insert.
  • std::array<T, N> — fixed-size, stack-allocated.
  • std::deque<T> — double-ended queue; O(1) push/pop at both ends; not contiguous.

11. map vs unordered_map?

std::mapstd::unordered_map
BackingRed-black treeHash table
Ordered keys✅❌
findO(log n)O(1) average
Worst caseO(log n)O(n)
MemoryLowerHigher

12. emplace_back vs push_back?

push_back(T) copies/moves an existing object. emplace_back(args...) constructs the object in place inside the container, avoiding a temporary. Prefer emplace_back when constructing.

Templates

13. Function template vs class template?

  • Function template — template<typename T> T add(T a, T b) { return a + b; }.
  • Class template — template<typename T> class Stack { … }.

14. What is template specialisation?

A specific implementation for a particular type:

cpp
template<typename T> struct Trait { static const bool isPointer = false; };
template<typename T> struct Trait<T*> { static const bool isPointer = true; };

15. auto in C++ — when and why?

  • auto lets the compiler deduce the type. Reduces verbosity, especially with iterators, lambdas, templates.
  • Use it when the type is obvious from context or genuinely complicated. Don't use it when it hides important information.

Modern C++ (17 / 20 / 23)

16. Range-based for, structured bindings?

cpp
for (const auto& [key, value] : myMap) {   // C++17 structured binding
    std::cout << key << " => " << value;
}

17. std::optional vs std::variant vs std::any?

  • std::optional<T> — T or nothing. Replaces "magic value" sentinels.
  • std::variant<A, B, C> — exactly one of a fixed set of types (tagged union).
  • std::any — any type at all (use sparingly).

18. C++20 highlights?

  • Modules — replace headers (gradually adopted).
  • Concepts — constrain templates with readable predicates.
  • Coroutines — co_await, co_return.
  • Ranges — composable lazy views.
  • std::format — Python-style formatting.

19. C++23 highlights?

  • std::print — finally a built-in print().
  • Deducing this — explicit object parameter.
  • std::expected<T, E> — error handling without exceptions.
  • Multidimensional operator[].

Concurrency

20. std::thread vs std::async vs std::jthread?

  • std::thread — manual; you must join() or detach() before destruction.
  • std::async — returns a future; runtime decides if launched in a new thread or deferred.
  • std::jthread (C++20) — auto-joining thread + built-in cancellation.

21. Race condition vs deadlock?

  • Race condition — multiple threads access shared data without synchronisation, result depends on timing.
  • Deadlock — two or more threads each hold a lock the other needs and wait forever. Avoid with consistent lock ordering or std::scoped_lock (acquires multiple atomically).