25 questions · Updated
C++ Interview Questions and Answers
C++ interviews go deeper into memory and object lifetime than almost any other language interview. Interviewers want to know whether you understand what happens when objects are created, copied, moved and destroyed, how virtual dispatch works, why RAII and smart pointers matter, and how to avoid undefined behaviour. Systems, game, embedded, trading and infrastructure roles all lean on these fundamentals. This page collects 25 C++ interview questions and answers, ordered from beginner to advanced, followed by C++ coding exercises such as implementing a simple unique_ptr, reversing a string in place and writing a thread-safe queue. Answers use modern C++ (C++17 and C++20): smart pointers instead of raw new and delete, move semantics, constexpr, std::optional and std::variant, and C++20 concepts, ranges and coroutines, with a note on what C++23 added. Where older idioms still show up in legacy codebases, the answers say so. Answer each question aloud first, then open it to check, and be ready for follow-ups — C++ interviewers like to keep asking why.
Beginner C++ interview questions
1.What is the difference between a pointer and a reference?
A pointer is an object holding an address; it can be null, reseated to point elsewhere and needs explicit dereferencing. A reference is an alias for an existing object, must be initialised, cannot be null in valid code and cannot be reseated. Use references for parameters that must refer to an object, and pointers (preferably smart pointers or std::optional) when absence is meaningful.
2.What is the difference between the stack and the heap?
Stack memory holds local variables with automatic lifetime; allocation is fast and objects are destroyed when they go out of scope. The heap (free store) holds objects with dynamic lifetime, allocated with new or through containers and smart pointers, and is slower and prone to fragmentation. Large or variable-sized data belongs on the heap, usually managed by std::vector or std::unique_ptr.
3.What is RAII?
Resource Acquisition Is Initialization ties a resource's lifetime to an object's lifetime: the constructor acquires the resource and the destructor releases it. Because destructors run when objects go out of scope, including during stack unwinding from exceptions, resources such as memory, file handles and locks are released reliably. std::unique_ptr, std::lock_guard and std::fstream are RAII types.
{
std::lock_guard<std::mutex> guard(mtx); // locks
shared_counter++;
} // unlocks automatically, even if an exception is thrown4.What is the difference between struct and class?
The only language difference is default access: struct members and base classes are public by default, class members are private by default. By convention, struct is used for simple aggregates of data and class for types with invariants and behaviour.
5.What does const mean in different positions?
const int* p is a pointer to a const int (you cannot modify the int through p); int* const p is a const pointer (you cannot reseat p). A const member function promises not to modify the object's observable state, and only const member functions can be called on const objects. Passing large objects by const reference avoids copies while preventing modification.
6.What is function overloading and how does it differ from overriding?
Overloading defines several functions with the same name but different parameter lists in the same scope, resolved at compile time. Overriding replaces a virtual function of a base class in a derived class with the same signature, resolved at runtime through the vtable. Mark overrides with override so the compiler catches signature mismatches.
7.What is undefined behaviour?
Undefined behaviour is code whose result the standard does not define, such as dereferencing a null or dangling pointer, out-of-bounds access, signed integer overflow, data races or using an uninitialised variable. The compiler may assume it never happens, so the program can crash, appear to work or be optimised in surprising ways. Sanitizers (AddressSanitizer, UndefinedBehaviorSanitizer, ThreadSanitizer) help catch it.
Intermediate C++ interview questions
9.What are move semantics and rvalue references?
Move semantics let an object transfer its resources, such as a heap buffer, to another object instead of copying them. An rvalue reference (T&&) binds to temporaries and to objects cast with std::move, enabling move constructors and move assignment operators. After a move, the source is left in a valid but unspecified state. std::move itself does not move anything; it is only a cast.
10.What are the rule of three, rule of five and rule of zero?
Rule of three: if a class needs a custom destructor, copy constructor or copy assignment, it probably needs all three. Rule of five adds the move constructor and move assignment. Rule of zero: design classes so they need none of them, by holding resources in RAII members such as std::vector and std::unique_ptr, and let the compiler generate the special members.
11.How do virtual functions work?
A class with virtual functions typically has a vtable, a table of function pointers, and each object carries a hidden vptr to its class's vtable. A call through a base pointer or reference looks up the function in the vtable at runtime, enabling polymorphism. The cost is an indirect call and the loss of inlining in most cases. Constructors cannot be virtual, and calling virtual functions from constructors does not dispatch to derived overrides.
12.Why should base classes have a virtual destructor?
If you delete a derived object through a base class pointer and the base destructor is not virtual, the behaviour is undefined, and in practice the derived destructor is skipped, leaking resources. Any class meant to be used polymorphically should declare a public virtual destructor, or a protected non-virtual one if deletion through the base is not allowed.
13.What is iterator invalidation?
Some container operations make existing iterators, pointers and references invalid. Inserting into a std::vector can reallocate and invalidate all of them; erasing invalidates those at or after the erased element. std::list and std::map keep iterators to other elements valid. Using an invalidated iterator is undefined behaviour, so use the iterator returned by erase or the erase-remove idiom (std::erase_if in C++20).
14.How do you choose between vector, list, map and unordered_map?
std::vector is the default: contiguous, cache-friendly, with amortised O(1) push_back. std::list only wins for frequent splicing or stable iterators. std::map is a balanced tree with ordered keys and O(log n) operations; std::unordered_map is a hash table with average O(1) lookups but no ordering. For small collections, a sorted vector often beats both maps in practice.
15.What are lambdas and capture modes?
A lambda creates an unnamed function object. Captures copy variables by value ([x] or [=]) or reference them ([&x] or [&]); [this] captures the object pointer and [*this] copies the object. Capturing by reference is dangerous when the lambda outlives the variables, for example when stored or passed to another thread. Init captures such as [p = std::move(ptr)] move objects into the lambda.
Advanced C++ interview questions
16.What are C++20 concepts?
Concepts are named compile-time predicates on template parameters. They replace much of the SFINAE and enable_if machinery with readable constraints, and produce far clearer error messages when a type does not satisfy them. The standard library provides many, such as std::integral and std::ranges::range.
template <typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template <Numeric T>
T square(T x) { return x * x; }17.What other C++20 features should you know?
Ranges bring composable, lazy views such as views::filter and views::transform. Coroutines (co_await, co_yield, co_return) support generators and asynchronous code, though the standard library offered few ready-made coroutine types until C++23's std::generator. Modules aim to replace headers. Other additions include the three-way comparison operator <=>, designated initializers, std::span, std::format and consteval.
auto evens_squared = numbers
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * n; });18.What is perfect forwarding?
Perfect forwarding passes arguments through a function template while preserving whether they were lvalues or rvalues. It uses forwarding references (T&& where T is deduced) together with std::forward<T>(arg). It is how make_unique and emplace_back construct objects in place with the exact arguments given.
template <typename T, typename... Args>
std::unique_ptr<T> make(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}19.What is the C++ memory model and what are atomics for?
The memory model defines how threads interact through memory and when writes become visible to other threads. A data race — two threads accessing the same location without synchronization where at least one writes — is undefined behaviour. std::atomic provides race-free operations with configurable memory orders; the default, sequentially consistent, is the easiest to reason about, while acquire/release and relaxed orders trade simplicity for performance.
20.What is the difference between constexpr, consteval and constinit?
constexpr allows a function or variable to be evaluated at compile time when its inputs are constant, but the function can also run at runtime. consteval (C++20) requires every call to be evaluated at compile time. constinit (C++20) requires a static or thread-local variable to be initialised at compile time, avoiding the static initialisation order problem, without making it const.
C++ coding interview questions
21.Implement a minimal unique_ptr.
Own a raw pointer, delete it in the destructor, delete the copy operations and implement move operations that transfer ownership and null out the source. This shows you understand RAII, the rule of five and move semantics.
template <typename T>
class UniquePtr {
T* ptr_ = nullptr;
public:
explicit UniquePtr(T* p = nullptr) : ptr_(p) {}
~UniquePtr() { delete ptr_; }
UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr&) = delete;
UniquePtr(UniquePtr&& o) noexcept : ptr_(std::exchange(o.ptr_, nullptr)) {}
UniquePtr& operator=(UniquePtr&& o) noexcept {
if (this != &o) { delete ptr_; ptr_ = std::exchange(o.ptr_, nullptr); }
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* get() const { return ptr_; }
};22.Reverse a string in place.
std::reverse does it in one line; in an interview, also show the two-pointer swap loop. Both are O(n) time and O(1) extra space.
void reverse_in_place(std::string& s) {
for (std::size_t i = 0, j = s.size(); i + 1 < j; ++i, --j)
std::swap(s[i], s[j - 1]);
}23.Write a thread-safe queue.
Protect a std::queue with a mutex and use a condition variable so consumers wait without busy-spinning. Always wait with a predicate to handle spurious wakeups, and notify after releasing or while holding the lock.
template <typename T>
class SafeQueue {
std::queue<T> q_;
std::mutex m_;
std::condition_variable cv_;
public:
void push(T value) {
{ std::lock_guard lock(m_); q_.push(std::move(value)); }
cv_.notify_one();
}
T pop() {
std::unique_lock lock(m_);
cv_.wait(lock, [&] { return !q_.empty(); });
T value = std::move(q_.front());
q_.pop();
return value;
}
};24.Remove all even numbers from a vector.
Since C++20, std::erase_if does it in one call. Before that, the erase-remove idiom moves kept elements to the front with std::remove_if and erases the tail. Both are O(n), unlike calling erase inside a loop, which is O(n²) and easy to get wrong with iterator invalidation.
std::erase_if(v, [](int n) { return n % 2 == 0; }); // C++20
v.erase(std::remove_if(v.begin(), v.end(), [](int n) { return n % 2 == 0; }), v.end()); // pre-C++2025.Detect a cycle in a linked list.
Floyd's tortoise-and-hare algorithm moves one pointer one step and another two steps at a time; if there is a cycle they eventually meet, otherwise the fast pointer reaches the end. O(n) time and O(1) space.
bool has_cycle(const Node* head) {
const Node *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) return true;
}
return false;
}Preparing for a C++ interview
Common questions about getting ready
How do I prepare for a C++ interview?
Master object lifetime first: constructors, destructors, copy and move, RAII and smart pointers. Then review virtual dispatch, templates, the STL containers and their complexity, and concurrency basics. Finally, practise data structures and algorithms problems in C++ so the STL feels natural under time pressure.
Which C++ standard should I know?
C++17 is the safe baseline, and C++20 features such as concepts, ranges and std::span are increasingly expected. Many companies still maintain older code, so be ready to recognise pre-C++11 idioms too.
Are C++ interviews harder than other language interviews?
They tend to go deeper into memory, lifetime and undefined behaviour, and interviewers often keep asking follow-up questions until you reach the edge of your knowledge. Saying clearly where you are unsure is better than guessing.
Do C++ interviews include system design?
For senior roles, yes, often with a performance or low-latency angle: memory layout, cache behaviour, lock-free structures and threading models. Low-level design questions on class hierarchies are also common.

