In this article
Memory and ownership
Memory questions open most C++ rounds, and they sit beside algorithm questions in the coding interviews path.
What is the difference between a pointer and a reference?
A reference is an alias for an object that already exists, and it must be initialized to refer to a valid object. A pointer is an object that holds an address, can be null, and can be reassigned. cppreference on references, read Oct 2026 adds that references are not objects, so there are no arrays of references or pointers to references. Use a reference when the target always exists.
Why it is asked: it tests whether you know what can be null and what can be rebound.
What is a dangling reference and how does one happen?
A dangling reference is a reference that still exists after the object it refers to has been destroyed; any use of it is undefined behavior. The reference page says a reference always refers to a valid object when initialized, but the program can destroy that object afterward. Returning a reference to a local variable is the standard example. Return by value, or return a reference to something that outlives the call.
Why it is asked: it shows whether you think about how long objects live, not just syntax.
What is RAII?
Resource Acquisition Is Initialization (RAII) ties a resource to the lifespan of an object: the constructor acquires the resource and the destructor releases it. cppreference on RAII, read Oct 2026 lists memory, open files and locked mutexes as examples. Because destructors run when a scope ends, even on an exception or early return, the resource is released. Containers, smart pointers and lock wrappers all follow it.
Why it is asked: it is the idea behind most C++ resource safety.
What is the difference between unique_ptr and shared_ptr?
A smart pointer is an object that owns another object through a pointer and deletes it automatically. A std::unique_ptr has one owner and is move-only: copying it does not compile, which the checks confirmed.1 A std::shared_ptr lets several owners share one object, which is destroyed when the last owner goes away (unique_ptr on cppreference page and shared_ptr on cppreference page, read Oct 2026). Default to unique_ptr.
Why it is asked: it checks whether you choose ownership deliberately.
How does shared_ptr count owners, and what is weak_ptr for?
The control block, a small heap record shared by all owners, keeps two counts, the number of shared_ptr owners and the number of weak_ptr observers. The object is destroyed when the owner count reaches zero, and the control block is freed only after the weak count also reaches zero (cppreference on shared_ptr, read Oct 2026). A weak_ptr watches without owning. In the run, two owners gave a count of 2 and the watcher reported expired after both were reset.1
Why it is asked: it separates using shared_ptr from understanding it.
Text description of the diagram
- A unique_ptr has one owner and is move-only.
- A shared_ptr lets several owners share one object, and a weak_ptr observes without owning.
Is shared_ptr thread-safe?
Partly. The reference says different shared_ptr objects can be used from different threads without extra synchronization, even if they share one object, but accessing the same shared_ptr object from several threads with a non-const operation is a data race (two threads touching the same memory at once, at least one writing, with no synchronization). The pointed-to object itself is not protected at all. Use a mutex (a lock that lets one thread at a time into a section of code) for the object, or std::atomic<shared_ptr> (C++20) for the pointer (cppreference on shared_ptr, read Oct 2026).
Why it is asked: the half-true answer "yes" is a common trap.
What is the difference between delete and delete[]?
Use delete for what new made and delete[] for what new[] made. The working draft says the operand of delete may be a null pointer or a pointer from a non-array new-expression (or to a base-class part of such an object), "if not, the behavior is undefined"; for delete[] the operand may be a null pointer or a pointer from an array new-expression, with no base-class allowance, so deleting an array through a base-class pointer is undefined behavior (expr.delete, read Oct 2026). Deleting a null pointer is a no-op for both delete and delete[]. In modern code, prefer std::vector or std::unique_ptr<T[]> so the question never arises.
Why it is asked: it tests precision about undefined behavior.
What is undefined behavior?
Undefined behavior means the language places no restrictions on what the program does once a rule is broken. cppreference on undefined behavior, read Oct 2026 lists data races, out-of-bounds access, signed integer overflow and null pointer dereference as examples. Compilers need not diagnose it, and with optimization on they may assume it never happens, so the result can look impossible from the source.
Why it is asked: it separates "it works on my machine" from correct code.
Classes and object life cycle
What are the rule of three, five and zero?
The rule of three says that a class needing a custom destructor, copy constructor or copy assignment operator almost certainly needs all three. The rule of five is the same advice extended with the move constructor and move assignment, since declaring any of the first three suppresses the implicit moves. The rule of zero says most classes should declare none and let members such as std::string manage themselves (cppreference on special member functions, read Oct 2026).
Why it is asked: it tests whether you know the special member functions interact.
What does std::move do?
It does not move anything. std::move is a cast to an rvalue reference (a reference that binds to a temporary or about-to-be-discarded object, as opposed to an lvalue, which has a name and an address), equivalent to a static_cast, which lets a move constructor or move assignment be chosen; the transfer happens there (cppreference on std::move, read Oct 2026). Standard library objects that were moved from are left in a valid but unspecified state, so assign to them or clear them, and do not rely on their value.
Why it is asked: "move semantics" is a standard follow-up to the rule of five.
How do virtual functions work?
A virtual function supports dynamic dispatch. Dynamic dispatch is the rule that a call through a base reference or pointer runs the most-derived override, even when the compiler cannot know the real type. Calling Base::f() by qualified name suppresses the dispatch (cppreference on virtual functions, read Oct 2026). In the run, a Derived object seen through a Base reference answered "derived", and the qualified call answered "base".1
Why it is asked: it is the base of polymorphism questions.
Why should a base class destructor be virtual?
Deleting a derived object through a base pointer is undefined behavior unless the base destructor is virtual; the working draft requires that "the static type shall have a virtual destructor" in that case (expr.delete, read Oct 2026). The virtual-function page gives the guideline: a base destructor should be public and virtual, or protected and non-virtual.
Why it is asked: it is the most common polymorphism trap.
What do override and final do?
override makes the compiler check that a function really overrides a virtual base function, so a mismatched signature is an error instead of a silent new function. final forbids further overriding, or, on a class, further derivation (cppreference on virtual functions, read Oct 2026). Both arrived in C++11. Mark every override with override.
Why it is asked: it checks modern C++ habits.
What is the difference between const, constexpr and consteval?
const makes an object read-only after initialization, and its initializer may be a runtime value. constexpr says a value or function can appear in a constant expression and be evaluated at compile time, though a constexpr function can still run at runtime. consteval, from C++20, requires every call to be a compile-time evaluation (cppreference on constexpr, read Oct 2026 and cppreference on consteval, read Oct 2026). The check compiled factorial(5) as 120 in a static_assert.1
Why it is asked: it tests compile-time versus run-time reasoning.
Knowing it is half the job. Saying it is the other half.
Interview Clozo is an AI interview copilot for real interview rounds: it hears the question and puts a strong answer on your screen, and you say it in your own words. See the features or how it works.
Start Free Trial →Containers
How does a vector grow, and what does reserve do?
A std::vector stores elements contiguously and push_back is amortized constant time (cheap on average, even though an occasional push copies everything), because it reallocates only when capacity runs out and allocates extra room. reserve allocates capacity up front so later pushes do not reallocate (cppreference on vector, read Oct 2026). On the machine used here, capacity went 1, 2, 4, 8 and on doubling up to 2048 for 1,100 pushes; the standard does not fix the growth factor.1
Why it is asked: it tests amortized cost and memory behavior together.
When are vector iterators and references invalidated?
When a push_back or insert changes capacity, every iterator, pointer and reference into the vector is invalidated; if capacity does not change, only positions at or after the change are (cppreference on vector, read Oct 2026). Iterator invalidation is the name for an iterator, pointer or reference that no longer points at a valid element, and it is a classic source of crashes. Call reserve when you hold pointers across pushes, or hold indices instead.
Why it is asked: it separates people who debugged real code from those who read a list.
What is the difference between map and unordered_map?
std::map keeps keys sorted, with logarithmic search, insertion and removal, and is usually a red-black tree. std::unordered_map organizes elements into buckets by hash, so search, insertion and removal are average constant time and iteration order is unspecified (map on cppreference page and unordered_map on cppreference page, read Oct 2026). The run printed map keys 1, 2, 3 in order. See also hashmap versus hashset.1
Why it is asked: it tests ordering against speed.
Why is a vector of bool special?
The standard library provides a vector<bool> specialization that may be optimized for space, and the container promises of std::vector, including contiguous storage, apply "for T other than bool" (cppreference on vector, read Oct 2026). Its element reference is a proxy, not bool&, which the run confirmed, so you cannot take a plain pointer to an element.1 If you need real references to elements or contiguous storage, use std::vector<char> (contiguous, with char& references) or std::deque<bool> (real bool& references, not contiguous); std::bitset is a fixed-size bit set and also uses a proxy reference.
Why it is asked: it is a known surprise in the standard library.
Language features
How do lambda captures work?
A lambda is an unnamed function object that can capture variables from the enclosing scope. Capture by copy stores a copy when the lambda is created; capture by reference refers to the original and does not keep it alive, so using it after the variable is gone is undefined behavior (cppreference on lambdas, read Oct 2026). After both variables changed from 1 to 2, the copy capture returned 1 and the reference capture returned 2.1
Why it is asked: capturing by reference is a common source of bugs.
What is a forwarding reference?
A forwarding reference is a T&& parameter of a function template, or auto&&, that preserves the value category of its argument (whether it was an lvalue or an rvalue) so std::forward can pass it on unchanged (cppreference on references, read Oct 2026). A named rvalue reference is itself an lvalue in an expression, which is why forwarding needs std::forward. It is not the same as a plain rvalue reference.
Why it is asked: it tests template and move semantics together.
How should you pass arguments to functions?
The C++ Core Guidelines (document last updated June 2026) rule F.16 says to pass cheaply copied types by value and others by reference to const for "in" parameters. An int goes by value; a long string goes by const std::string&. If the function must keep its own copy, passing by value and moving is a common variant.
Why it is asked: it shows whether you weigh copy cost.
Threads
What do lock_guard and scoped_lock do?
std::lock_guard is an RAII wrapper that locks a mutex when constructed and unlocks it when destroyed, so the lock is released on every exit path. std::scoped_lock, from C++17, can lock several mutexes at once using a deadlock-avoidance algorithm (cppreference on lock_guard, read Oct 2026). Always name the guard: an unnamed temporary is destroyed immediately and holds no lock. More in the concurrency questions.
Why it is asked: it applies RAII to the most common threading task.
Preparing
How do you prepare for C++ programming interview questions?
Write and run small programs for each answer above, because most of these topics are about behavior you can observe. Read the C++ Core Guidelines for the reasoning behind rules, and practise saying why, not just what. Pair this with low-level design practice and the system design guide.
Why it is asked: it shows whether your preparation matches the round.
Where C++ appears in interview loops
C++ questions are common in systems, game, trading and embedded roles, often as a language-depth round next to a coding round. The interview loops guide shows where each round type fits. If you also interview in another object-oriented language, compare the answers with Java object-oriented questions: the ideas of polymorphism and ownership recur, but the rules differ.
- RAII ties a resource to an object, so scope exit releases it on every path.
- Prefer plain values, then unique_ptr, then shared_ptr; weak_ptr only observes.
- Virtual dispatch needs a virtual base destructor, and override catches signature mistakes.
- A vector's reallocation invalidates every iterator, pointer and reference into it.
- Undefined behavior means the language promises nothing, so rely on the reference, not on "it ran".
Sources
- C++ standard working draft: expr.delete — ISO C++ committee working draft, as hosted at eel.is (read date), 24 Oct 2026
- C++ Core Guidelines — Standard C++ Foundation (Stroustrup, Sutter, editors); the document's own last-updated line, 14 Jun 2026
- std::unique_ptr, cppreference — cppreference.com (no revision date retrieved; date = read date), 24 Oct 2026
- std::shared_ptr, cppreference — cppreference.com (date = read date), 24 Oct 2026
- Virtual function specifier, cppreference — cppreference.com (date = read date), 24 Oct 2026
- std::vector, cppreference — cppreference.com (date = read date), 24 Oct 2026
- Undefined behavior, cppreference — cppreference.com (date = read date), 24 Oct 2026
- The rule of three, five and zero, cppreference — cppreference.com (date = read date), 24 Oct 2026
- References, cppreference — cppreference.com (date = read date), 24 Oct 2026
- RAII, cppreference — cppreference.com (date = read date), 24 Oct 2026
- std::move, cppreference — cppreference.com (date = read date), 24 Oct 2026
- constexpr specifier, cppreference — cppreference.com (date = read date), 24 Oct 2026
- consteval specifier, cppreference — cppreference.com (date = read date), 25 Oct 2026
- std::map, cppreference — cppreference.com (date = read date), 24 Oct 2026
- std::unordered_map, cppreference — cppreference.com (date = read date), 24 Oct 2026
- Lambda expressions, cppreference — cppreference.com (date = read date), 24 Oct 2026
- std::lock_guard, cppreference — cppreference.com (date = read date), 24 Oct 2026