Tutorials Logic, IN info@tutorialslogic.com
C++

Top 50 C++ Interview Questions

Curated questions covering OOP, STL, templates, memory management, virtual functions, smart pointers, and modern C++11/14/17/20 features.

01

What is C++ and how does it differ from C?

C++ is a general-purpose language extending C with OOP, templates, exceptions, and the STL. Key additions over C: classes and objects, inheritance, polymorphism, encapsulation, function/operator overloading, references, templates, exceptions, and the Standard Template Library.

02

What is the difference between class and struct in C++?

  • class - members are private by default. Used for OOP with encapsulation.
  • struct - members are public by default. Used for plain data structures (POD types).
  • Both support inheritance, methods, and access specifiers. The only real difference is default access.
Example
struct Point { int x, y; };  // public by default
class Circle { int radius; }; // private by default
03

What are the four pillars of OOP in C++?

  • Encapsulation - bundling data and methods; hiding internal state via access specifiers (public, protected, private).
  • Inheritance - a class acquires properties of another using : public Base.
  • Polymorphism - virtual functions enable runtime polymorphism; function overloading enables compile-time polymorphism.
  • Abstraction - pure virtual functions and abstract classes define interfaces.
04

What is the difference between public, protected, and private inheritance?

  • public inheritance - public and protected members of base remain public/protected in derived. Models is-a relationship.
  • protected inheritance - public and protected members of base become protected in derived.
  • private inheritance - all members of base become private in derived. Models implemented-in-terms-of.
Example
class Animal {};
class Dog : public Animal {};     // is-a
class Engine {};
class Car : private Engine {};    // implemented-in-terms-of
05

What is a virtual function and how does it enable polymorphism?

A virtual function is declared with the virtual keyword in the base class. When called through a base class pointer/reference, the derived class version is called at runtime (dynamic dispatch via vtable).

Example
class Shape {
public:
  virtual double area() const = 0;  // pure virtual
  virtual ~Shape() {}               // virtual destructor
};
class Circle : public Shape {
  double r;
public:
  Circle(double r) : r(r) {}
  double area() const override { return 3.14 * r * r; }
};
Shape* s = new Circle(5);
printf("%.2f", s->area());  // calls Circle::area()
06

What is the difference between virtual and pure virtual functions?

  • virtual function - has a default implementation in the base class. Derived classes can override it.
  • pure virtual function (= 0) - no implementation in base class. Derived classes MUST override it. Makes the class abstract.
  • A class with at least one pure virtual function is abstract and cannot be instantiated.
Example
class Base {
public:
  virtual void foo() { cout << "Base"; }  // virtual
  virtual void bar() = 0;                 // pure virtual
};
07

What is the difference between function overloading and function overriding?

  • Overloading - same function name, different parameters in the same class. Resolved at compile time.
  • Overriding - derived class provides a new implementation of a virtual function from the base class. Resolved at runtime.
Example
// Overloading
void print(int x) {}
void print(double x) {}

// Overriding
class Base { virtual void show() { cout << "Base"; } };
class Derived : public Base { void show() override { cout << "Derived"; } };
08

What is a constructor and what are its types?

  • Default constructor - no parameters. Called when object is created without arguments.
  • Parameterized constructor - takes arguments to initialize members.
  • Copy constructor - creates a new object as a copy of an existing one.
  • Move constructor (C++11) - transfers resources from a temporary object.
Example
class MyClass {
public:
  MyClass() {}                          // default
  MyClass(int x) : val(x) {}            // parameterized
  MyClass(const MyClass& o) : val(o.val) {} // copy
  MyClass(MyClass&& o) : val(o.val) { o.val = 0; } // move
private:
  int val;
};
09

What is the difference between copy constructor and assignment operator?

  • Copy constructor - called when a new object is created from an existing one. MyClass b = a; or MyClass b(a);
  • Assignment operator (=) - called when an existing object is assigned from another. b = a; (b already exists).
  • Both should be defined when a class manages resources (Rule of Three/Five).
Example
MyClass a(5);
MyClass b = a;  // copy constructor
MyClass c;
c = a;          // assignment operator
10

What is the Rule of Three/Five/Zero?

  • Rule of Three - if you define any of: destructor, copy constructor, copy assignment operator, you should define all three.
  • Rule of Five (C++11) - extends Rule of Three with move constructor and move assignment operator.
  • Rule of Zero - prefer using smart pointers and STL containers so you need none of the five.
11

What is a destructor and when is it called?

A destructor (~ClassName) is called automatically when an object goes out of scope or is deleted. Used to release resources. Always declare destructors virtual in base classes to ensure proper cleanup of derived objects.

Example
class Resource {
  int* data;
public:
  Resource() { data = new int[100]; }
  ~Resource() { delete[] data; }  // cleanup
};

class Base {
public:
  virtual ~Base() {}  // virtual destructor - essential!
12

What is the difference between new/delete and malloc/free?

  • new/delete - C++ operators. Call constructors/destructors. Type-safe. Throw std::bad_alloc on failure.
  • malloc/free - C functions. Do NOT call constructors/destructors. Return void*. Return NULL on failure.
  • Always use new/delete in C++. Never mix them.
Example
int* p = new int(42);    // calls constructor
delete p;                // calls destructor

int* arr = new int[10];
delete[] arr;            // use delete[] for arrays
13

What are smart pointers in C++11?

Smart pointers automatically manage memory, preventing leaks. Defined in .

  • unique_ptr - exclusive ownership. Cannot be copied, only moved. Automatically deleted when out of scope.
  • shared_ptr - shared ownership via reference counting. Deleted when last shared_ptr is destroyed.
  • weak_ptr - non-owning reference to a shared_ptr. Breaks circular references.
Example
auto up = make_unique<int>(42);  // unique ownership
auto sp = make_shared<int>(42);  // shared ownership
weak_ptr<int> wp = sp;           // non-owning

// No manual delete needed!
14

What is the difference between unique_ptr and shared_ptr?

  • unique_ptr - single owner. Cannot be copied. Can be moved. Zero overhead over raw pointer.
  • shared_ptr - multiple owners. Reference counted. Slightly more overhead. Use when ownership is shared.
Example
auto u = make_unique<MyClass>();
// auto u2 = u;  // ERROR: cannot copy
auto u2 = move(u);  // OK: transfer ownership

auto s1 = make_shared<MyClass>();
auto s2 = s1;  // OK: both own the object
15

What is RAII (Resource Acquisition Is Initialization)?

RAII is a C++ idiom where resource acquisition (memory, file handles, locks) is tied to object lifetime. Resources are acquired in the constructor and released in the destructor. Smart pointers, std::fstream, and std::lock_guard all use RAII.

Example
class FileHandle {
  FILE* fp;
public:
  FileHandle(const char* name) { fp = fopen(name, "r"); }
  ~FileHandle() { if (fp) fclose(fp); }  // auto-cleanup
};
// File is automatically closed when FileHandle goes out of scope
16

What is the STL and what are its main components?

The Standard Template Library provides generic containers, algorithms, and iterators.

  • Containers: vector, list, deque, set, map, unordered_map, stack, queue, priority_queue.
  • Algorithms: sort, find, count, transform, accumulate, binary_search.
  • Iterators: connect containers and algorithms.
  • Function objects (functors) and lambdas.
Example
vector<int> v = {3,1,4,1,5};
sort(v.begin(), v.end());
auto it = find(v.begin(), v.end(), 4);
accumulate(v.begin(), v.end(), 0);  // sum
17

What is the difference between vector and list?

  • vector - dynamic array. O(1) random access. O(n) insertion/deletion in middle. Contiguous memory (cache-friendly).
  • list - doubly linked list. O(n) random access. O(1) insertion/deletion anywhere. Non-contiguous memory.
  • Use vector for most cases; list only when frequent mid-sequence insertions are needed.
Example
vector<int> v = {1,2,3};
v.push_back(4);    // O(1) amortized
v[2];              // O(1) random access

list<int> l = {1,2,3};
auto it = l.begin();
advance(it, 1);
l.insert(it, 99);  // O(1) insertion
18

What is the difference between map and unordered_map?

  • map - sorted by key (red-black tree). O(log n) for insert/find/delete. Keys must be comparable.
  • unordered_map - hash table. O(1) average for insert/find/delete. Keys must be hashable.
  • Use unordered_map for performance; map when sorted order is needed.
Example
map<string,int> m;           // sorted, O(log n)
unordered_map<string,int> um; // hash, O(1) avg
m["key"] = 1;
um["key"] = 1;
19

What are templates in C++?

Templates enable generic programming - writing code that works with any type. Function templates and class templates are instantiated by the compiler for each type used.

Example
// Function template
template<typename T>
T max(T a, T b) { return a > b ? a : b; }

max(3, 5);       // T = int
max(3.14, 2.71); // T = double

// Class template
template<typename T>
class Stack {
  vector<T> data;
public:
  void push(T val) { data.push_back(val); }
  T pop() { T v = data.back(); data.pop_back(); return v; }
};
20

What is template specialization?

Template specialization provides a custom implementation for a specific type, overriding the generic template.

Example
template<typename T>
void print(T val) { cout << val; }  // generic

// Specialization for bool
template<>
void print<bool>(bool val) {
  cout << (val ? "true" : "false");
}
21

What is the difference between references and pointers?

  • Reference - alias for an existing variable. Cannot be null. Cannot be reassigned to refer to another variable. No dereferencing needed.
  • Pointer - stores a memory address. Can be null. Can be reassigned. Must be dereferenced with *.
  • Prefer references when null is not needed; use pointers for optional values and dynamic allocation.
Example
int x = 5;
int& ref = x;   // reference - must be initialized
ref = 10;       // modifies x directly

int* ptr = &x;  // pointer
*ptr = 10;      // must dereference
22

What is the difference between const reference and value parameter?

  • Value parameter - copies the argument. Safe but expensive for large objects.
  • const reference parameter - no copy. Cannot modify the argument. Efficient for large objects.
  • Use const& for large objects (strings, vectors, custom classes); use value for primitives.
Example
void byValue(string s) {}         // copies string
void byConstRef(const string& s) {} // no copy, read-only
void byRef(string& s) {}           // no copy, can modify
23

What is move semantics in C++11?

Move semantics allow transferring resources from a temporary (rvalue) object instead of copying them. This avoids expensive deep copies. Use std::move() to cast to rvalue reference.

Example
vector<int> v1 = {1,2,3,4,5};
vector<int> v2 = move(v1);  // v1 is now empty, no copy

// Move constructor
MyClass(MyClass&& other) noexcept
  : data(other.data) {
  other.data = nullptr;  // transfer ownership
}
24

What is the difference between lvalue and rvalue?

  • lvalue - has a persistent memory address. Can appear on left side of assignment. Examples: variables, array elements.
  • rvalue - temporary value with no persistent address. Cannot appear on left side. Examples: literals, function return values, expressions.
  • rvalue reference (T&&) - binds to rvalues. Enables move semantics.
Example
int x = 5;    // x is lvalue, 5 is rvalue
int& r = x;   // lvalue reference
int&& rr = 5; // rvalue reference
int&& rr2 = move(x); // cast lvalue to rvalue
25

What are lambda expressions in C++11?

Lambdas are anonymous function objects. Syntax: [capture](params) -> return_type { body }.

Example
auto add = [](int a, int b) { return a + b; };
cout << add(3, 4);  // 7

// Capture by value and reference
int x = 10;
auto f1 = [x]() { return x; };    // capture by value
auto f2 = [&x]() { x++; };        // capture by reference
auto f3 = [=]() { return x; };    // capture all by value
auto f4 = [&]() { x++; };         // capture all by reference

// With STL
vector<int> v = {3,1,4,1,5};
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
26

What is the difference between std::sort and std::stable_sort?

  • std::sort - O(n log n). Not stable (equal elements may be reordered). Faster.
  • std::stable_sort - O(n log n) but preserves relative order of equal elements. Slightly slower.
Example
vector<int> v = {3,1,4,1,5,9};
sort(v.begin(), v.end());         // ascending
sort(v.begin(), v.end(), greater<int>()); // descending
stable_sort(v.begin(), v.end()); // preserves equal order
27

What is the difference between stack and queue in STL?

  • stack - LIFO (Last In First Out). Operations: push(), pop(), top(). Backed by deque by default.
  • queue - FIFO (First In First Out). Operations: push(), pop(), front(), back(). Backed by deque by default.
  • priority_queue - max-heap by default. Top element is always the largest.
Example
stack<int> s;
s.push(1); s.push(2);
cout << s.top();  // 2 (LIFO)

queue<int> q;
q.push(1); q.push(2);
cout << q.front(); // 1 (FIFO)
28

What is the difference between set and multiset?

  • set - stores unique elements in sorted order. O(log n) insert/find/delete.
  • multiset - allows duplicate elements. Otherwise same as set.
  • unordered_set - hash-based, O(1) average, no ordering, unique elements.
Example
set<int> s = {3,1,4,1,5};  // {1,3,4,5} - no duplicates
multiset<int> ms = {3,1,4,1,5}; // {1,1,3,4,5} - duplicates OK
29

What is the difference between emplace_back and push_back?

  • push_back(val) - copies or moves an existing object into the container.
  • emplace_back(args...) - constructs the object in-place using the provided arguments. Avoids creating a temporary object. More efficient.
Example
vector<pair<int,string>> v;
v.push_back({1, "hello"});       // creates temporary, then moves
v.emplace_back(1, "hello");      // constructs in-place, no temporary
30

What is the difference between auto and decltype?

  • auto - deduces the type of a variable from its initializer at compile time.
  • decltype(expr) - deduces the type of an expression without evaluating it.
Example
auto x = 42;          // int
auto v = vector<int>(); // vector<int>

int a = 5;
decltype(a) b = 10;   // int (same type as a)
decltype(a + 1.0) c;  // double
31

What is the difference between nullptr and NULL in C++?

  • NULL - C-style macro defined as 0 or (void*)0. Can cause ambiguity in overloaded functions.
  • nullptr (C++11) - a keyword of type nullptr_t. Type-safe. Unambiguous in overloaded functions.
  • Always use nullptr in C++11 and later.
Example
void f(int x) { cout << "int"; }
void f(int* p) { cout << "ptr"; }

f(NULL);    // ambiguous - might call f(int)
f(nullptr); // unambiguous - calls f(int*)
32

What is the difference between override and final keywords?

  • override - explicitly marks a virtual function as overriding a base class function. Compile error if no matching virtual function exists.
  • final - prevents a virtual function from being overridden further, or prevents a class from being inherited.
Example
class Base { virtual void foo() {} };
class Derived : public Base {
  void foo() override {}  // compile error if Base::foo not virtual
};
class Leaf : public Derived {
  void foo() final {}  // cannot be overridden further
};
33

What is the difference between static_cast, dynamic_cast, const_cast, and reinterpret_cast?

  • static_cast - compile-time cast. Safe for related types (int to double, base to derived if you are sure).
  • dynamic_cast - runtime cast for polymorphic types. Returns nullptr (pointer) or throws (reference) if cast fails.
  • const_cast - adds or removes const qualifier.
  • reinterpret_cast - low-level bit reinterpretation. Unsafe. Use only for hardware/system programming.
Example
Base* b = new Derived();
Derived* d = dynamic_cast<Derived*>(b); // safe runtime cast
if (d) { /* cast succeeded */ }
34

What is the difference between std::string and C-style strings?

  • C-style string (char*) - null-terminated array. Manual memory management. No bounds checking. Unsafe.
  • std::string - class with automatic memory management. Bounds checking. Rich API. Safe.
  • Always prefer std::string in C++.
Example
string s = "Hello";
s += " World";      // easy concatenation
s.length();         // 11
s.substr(0, 5);     // "Hello"
s.find("World");    // 6
35

What is the difference between std::array and std::vector?

  • std::array - fixed-size array. Size known at compile time. Stack-allocated. No overhead.
  • std::vector - dynamic array. Size can change at runtime. Heap-allocated. Slightly more overhead.
  • Use std::array for fixed-size collections; vector for dynamic collections.
Example
array<int, 5> arr = {1,2,3,4,5};  // fixed size
vector<int> v = {1,2,3};          // dynamic
v.push_back(4);                    // can grow
36

What is the difference between std::optional and raw pointers for optional values?

std::optional (C++17) represents a value that may or may not be present. Safer than using nullptr as a sentinel value.

Example
optional<string> findUser(int id) {
  if (id == 1) return "Alice";
  return nullopt;  // no value
}

auto user = findUser(1);
if (user.has_value()) {
  cout << user.value();
}
cout << user.value_or("Unknown");
37

What is the difference between std::variant and union?

  • union - C-style. No type safety. No destructor called for complex types. Undefined behavior if wrong member accessed.
  • std::variant (C++17) - type-safe union. Tracks which type is active. Calls correct destructor.
Example
variant<int, string, double> v = 42;
v = "hello";
cout << get<string>(v);  // "hello"

// Type-safe visitor
visit([](auto& val) { cout << val; }, v);
38

What is the difference between std::any and void*?

  • void* - raw pointer to any type. No type information stored. Unsafe cast required.
  • std::any (C++17) - type-safe tl-container for any type. Stores type information. Throws bad_any_cast on wrong access.
Example
any a = 42;
a = string("hello");
cout << any_cast<string>(a);  // "hello"
// any_cast<int>(a);  // throws bad_any_cast
39

What is the difference between constexpr and const?

  • const - value cannot be changed after initialization. Evaluated at runtime or compile time.
  • constexpr (C++11) - value MUST be computable at compile time. Enables compile-time computation.
Example
const int x = 5;          // may be runtime
constexpr int y = 5;      // must be compile-time

constexpr int factorial(int n) {
  return n <= 1 ? 1 : n * factorial(n-1);
}
constexpr int f5 = factorial(5); // computed at compile time
40

What is the difference between std::thread and std::async?

  • std::thread - creates a new thread. Must be joined or detached. No return value mechanism.
  • std::async - runs a function asynchronously. Returns std::future to get the result. May or may not create a new thread.
Example
// Thread
thread t([]{ doWork(); });
t.join();

// Async
auto future = async(launch::async, []{ return compute(); });
int result = future.get();  // blocks until done
41

What is the difference between std::mutex and std::lock_guard?

  • std::mutex - provides mutual exclusion. Must manually lock() and unlock(). Risk of forgetting to unlock.
  • std::lock_guard - RAII wrapper for mutex. Automatically unlocks when it goes out of scope. Preferred.
  • std::unique_lock - more flexible than lock_guard. Supports deferred locking and condition variables.
Example
mutex mtx;

// Manual (risky)
mtx.lock();
// critical section
mtx.unlock();

// RAII (preferred)
{
  lock_guard<mutex> lock(mtx);
  // critical section - auto-unlocked
}
42

What is the difference between std::string_view and std::string?

std::string_view (C++17) is a non-owning, read-only view of a string. It does not copy the string data. Use it for function parameters that only need to read a string.

Example
void print(string_view sv) {  // no copy
  cout << sv;
}

string s = "Hello";
print(s);          // works
print("World");    // works - no allocation
print(s.substr(0,3)); // works - no copy
43

What is the difference between structured bindings and std::tie?

  • std::tie (C++11) - unpacks tuple/pair into existing variables.
  • Structured bindings (C++17) - declares new variables from tuple/pair/struct/array. Cleaner syntax.
Example
// std::tie
int a, b;
tie(a, b) = make_pair(1, 2);

// Structured bindings (C++17)
auto [x, y] = make_pair(1, 2);

map<string,int> m;
for (auto& [key, val] : m) {
  cout << key << ": " << val;
}
44

What is the difference between std::span and raw arrays?

std::span (C++20) is a non-owning view over a contiguous sequence of elements. It carries both a pointer and a size, making it safer than raw pointer + size pairs.

Example
void process(span<int> data) {
  for (int x : data) cout << x;
}

int arr[] = {1,2,3,4,5};
process(arr);  // works

vector<int> v = {1,2,3};
process(v);    // works - no copy
45

What is the difference between std::format and printf in C++20?

std::format (C++20) is a type-safe, extensible string formatting function. Unlike printf, it is type-safe (no format string mismatches), supports custom types, and returns a string.

Example
// printf - not type-safe
printf("Hello %s, you are %d years old\n", name, age);

// std::format (C++20) - type-safe
string s = format("Hello {}, you are {} years old", name, age);
cout << format("{:.2f}", 3.14159);  // "3.14"
46

What is the difference between std::ranges and traditional STL algorithms?

std::ranges (C++20) provides range-based versions of STL algorithms that work directly on containers without needing begin()/end() pairs. They also support views (lazy transformations) and pipelines.

Example
vector<int> v = {3,1,4,1,5,9};

// Traditional
sort(v.begin(), v.end());

// Ranges (C++20)
ranges::sort(v);

// Views pipeline
auto result = v | views::filter([](int x){ return x > 3; })
                | views::transform([](int x){ return x * 2; });
47

What is the difference between std::coroutine and regular functions?

Coroutines (C++20) are functions that can be suspended and resumed. They use co_await, co_yield, and co_return. Used for async programming, generators, and cooperative multitasking without threads.

Example
// Generator coroutine
generator<int> fibonacci() {
  int a = 0, b = 1;
  while (true) {
    co_yield a;
    tie(a, b) = make_pair(b, a + b);
  }
}
48

What is the difference between copy elision and move semantics?

  • Copy elision - compiler optimization that constructs an object directly in its final destination, avoiding copy or move construction.
  • Move semantics - transfers resources from a temporary or expiring object using rvalue references and move constructors.
  • Since C++17, some copy elision cases are guaranteed, especially returning prvalues from functions.
Example
class Buffer {
public:
  Buffer(Buffer&& other) noexcept;      // move constructor
  Buffer& operator=(Buffer&&) noexcept; // move assignment
};

Buffer makeBuffer() {
  return Buffer{}; // guaranteed copy elision in C++17
}
49

What is the Rule of Three, Rule of Five, and Rule of Zero?

  • Rule of Three - if a class defines destructor, copy constructor, or copy assignment, it probably needs all three.
  • Rule of Five - in C++11+, also consider move constructor and move assignment.
  • Rule of Zero - prefer standard containers and smart pointers so the compiler-generated special members are correct.
Example
class FileHandle {
  unique_ptr<FILE, decltype(&fclose)> file;
public:
  FileHandle(FILE* f) : file(f, fclose) {}
};
// Rule of Zero: unique_ptr owns cleanup safely.
50

What is the difference between noexcept and throw specifications?

noexcept tells the compiler and callers that a function should not throw. It helps optimization and affects move operations in standard containers. Old dynamic throw specifications like throw(Type) are deprecated/removed and should not be used.

Example
class Item {
public:
  Item(Item&& other) noexcept; // vector can move safely during reallocation
};

void save() noexcept {
  // must not let exceptions escape
}
Next Step

Use C++ interview prep to move into practice and application.

After reviewing interview answers, strengthen the same topic with tutorials, coding practice, or a stronger resume story.

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.