C++ interview questions for freshers
Basics from campus placements: C vs C++, compilation, operators, sizeof and tricky keywords.
What is C++ and how is it different from C?
A compiled, statically typed language that keeps almost all of C and adds classes, references, templates, exceptions, overloading, RAII and a library of containers and algorithms.
Not every C program is valid C++: int *p = malloc(4); needs a cast, and class and new are reserved words. The syntax fits in the C++ cheat sheet.
What happens when you compile a C++ program?
Preprocessing expands #include and macros, compilation turns each .cpp into assembly, assembly produces object files, and linking joins them with libraries into an executable.
"not declared in this scope" is a compiler error; "undefined reference to foo()" is a linker error, usually a missing .cpp or library.
What does this print: integer division and % with two ints?
#include <iostream>
using namespace std;
int main() {
int a = 7, b = 2;
cout << a / b << " " << a % b << " " << a / 2.0 << endl;
return 0;
}Predict the output
It prints 3 1 3.5. 7 / 2 with two ints truncates to 3, and 7 % 2 is 1. In a / 2.0 one operand is a double, so the result is 3.5.
Division truncates toward zero (guaranteed since C++11), so -7 / 2 is -3 and -7 % 2 is -1.
What does this print: a++ and ++a assigned to two variables?
#include <iostream>
using namespace std;
int main() {
int a = 5;
int b = a++;
int c = ++a;
cout << a << " " << b << " " << c << endl;
return 0;
}Predict the output
It prints 7 5 7. a++ returns the old value (5) and then makes a 6; ++a increments to 7 first and returns 7.
The trap is i++ + ++i, which modifies i twice without sequencing: undefined behavior, so no answer is right.
What is the difference between a struct and a class in C++?
Only the default access. Members and base classes of a struct are public by default; in a class they are private.
#include <iostream>
struct Point {
int x = 1; // public by default
};
class Account {
int balance = 100; // private by default
public:
int get() const { return balance; }
};
int main() {
Point p;
Account acc;
std::cout << p.x << " " << acc.get() << "\n";
// acc.balance would not compile: it is private
}This prints 1 100. By convention, struct is for plain data with no invariants and class for a type that protects its state.
What does this print: sizeof and strlen on a char array?
#include <iostream>
#include <cstring>
int main() {
char s[] = "hello";
std::cout << sizeof(s) << " " << strlen(s) << "\n";
}Predict the output
It prints 6 5. sizeof(s) is the size of the array, five letters plus the '\0'; strlen(s) counts up to the '\0'.
For a const char*, or an array passed to a function, sizeof gives the pointer's size (8 on 64-bit).
What does this print: sizeof of an empty class and a class with one int?
#include <iostream>
class Empty {};
class WithInt { int x; };
int main() {
std::cout << sizeof(Empty) << " " << sizeof(WithInt) << "\n";
}Predict the output
It prints 1 4. An empty class still has a nonzero size, 1 on every mainstream compiler, because every object must have its own address.
Used as a base class it may take zero bytes (the empty base optimization), and C++20's [[no_unique_address]] gives the same saving for an empty member (MSVC ignores it and needs [[msvc::no_unique_address]]; see the no_unique_address reference).
What is a namespace, and why is using namespace std; considered bad practice?
A namespace is a named scope that keeps names apart, so std::sort and mylib::sort can coexist. using namespace std; pulls every std name into scope; in a header it leaks into every includer, and names like count clash with yours. It is fine in a small .cpp file.
What is the difference between #include <file> and #include "file", and what are include guards?
#include <file> searches the system include paths; #include "file" usually searches the current file's directory first, then the system paths. An include guard stops a header from being pasted twice into one translation unit.
#ifndef SHAPE_H
#define SHAPE_H
class Shape { /* ... */ };
#endif
#pragma once does the same in one line; it is not standard, but GCC, Clang and MSVC support it.
What is the difference between std::endl and '\n'?
std::endl writes a newline and flushes the stream; '\n' only writes the newline. In a loop printing a million lines, the flushes can make endl several times slower.
Use '\n' by default and flush only when output must appear at once, such as a progress line. std::cerr flushes after every write anyway.
What is function overloading in C++?
Several functions share a name but differ in the number or types of parameters; the compiler picks one at compile time from the arguments.
#include <iostream>
using namespace std;
int area(int side) { return side * side; }
int area(int w, int h) { return w * h; }
double area(double r) { return 3.14159 * r * r; }
int main() {
cout << area(4) << " " << area(3, 5) << " " << area(1.0) << "\n";
}This prints 16 15 3.14159. The return type alone cannot tell overloads apart. Each name is mangled with its parameter types, and extern "C" turns that off. More in the function overloading docs.
What is an inline function in C++?
inline lets a function (and, since C++17, a variable) be defined in a header included by many .cpp files without breaking the one definition rule. Whether a call is inlined is the compiler's choice, keyword or not.
Unlike a macro it checks types and evaluates arguments once: #define SQ(x) x*x makes SQ(1+2) equal 5.
What are the uses of the static keyword in C++?
Four meanings: a local keeps its value between calls and is initialized once; a data member is shared by all objects; a member function has no this; and at namespace scope it gives internal linkage, visible only in that .cpp file.
#include <iostream>
int nextId() {
static int id = 0; // initialized once
return ++id;
}
struct Counter {
static int created;
Counter() { ++created; }
};
int Counter::created = 0;
int main() {
nextId();
nextId();
std::cout << nextId() << "\n";
Counter a, b, c;
std::cout << Counter::created << "\n";
}This prints 3 and then 3.
How does exception handling work in C++?
throw raises an exception object and the first catch whose type matches handles it. On the way, the stack unwinds and every local object in between is destroyed.
#include <iostream>
#include <stdexcept>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3};
try {
cout << v.at(5) << "\n";
} catch (const out_of_range&) {
cout << "out_of_range caught\n";
} catch (const exception& e) {
cout << "other: " << e.what() << "\n";
}
}This prints out_of_range caught. Catch by const& to avoid slicing and put the most derived handler first. An uncaught exception calls std::terminate. More in the try and catch docs.
What does this print on a typical 64-bit system: sizeof of two structs with the same members in a different order?
#include <iostream>
struct A { char c; int i; char d; };
struct B { int i; char c; char d; };
int main() {
std::cout << sizeof(A) << " " << sizeof(B) << "\n";
}Predict the output
It prints 12 8 on x86-64 and ARM64 with GCC, Clang or MSVC. An int must start at an address divisible by 4, so A gets 3 bytes of padding after c and 3 after d to keep its size a multiple of 4. In B the two chars share one padded block. Order members from largest to smallest alignment to save space.
OOPs in C++ interview questions
Classes, constructors, inheritance, virtual functions and polymorphism, with output questions on the vtable.
What are the four pillars of OOP and how does C++ support each one?
- Encapsulation:
privatedata behind public member functions. - Abstraction: abstract classes and narrow public interfaces.
- Inheritance:
public,protectedandprivate, including multiple inheritance. - Polymorphism: at compile time through overloading and templates, at runtime through virtual functions called via a base pointer or reference.
What are the types of constructors in C++?
Default, parameterized, copy and move (C++11), plus delegating and converting constructors. A move constructor steals the source's resources instead of copying them.
#include <iostream>
#include <string>
#include <utility>
using namespace std;
class Book {
public:
string title;
Book() : title("untitled") { cout << "default\n"; }
Book(string t) : title(t) { cout << "param\n"; }
Book(const Book& o) : title(o.title) { cout << "copy\n"; }
Book(Book&& o) noexcept : title(std::move(o.title)) { cout << "move\n"; }
};
int main() {
Book a;
Book b("Dune");
Book c = b;
Book d = std::move(b);
}This prints default, param, copy, move. Follow-up: why does the copy constructor take const Book&? Taking Book by value would need a copy, calling itself forever. See the constructors docs.
What does this print: constructor and destructor order with a base class?
#include <iostream>
using namespace std;
struct Base {
Base() { cout << "B "; }
~Base() { cout << "~B "; }
};
struct Derived : Base {
Derived() { cout << "D "; }
~Derived() { cout << "~D "; }
};
int main() {
Derived d;
}Predict the output
It prints B D ~D ~B. The Base part is built first, then Derived, and destruction runs in exactly the reverse order.
Members follow the same rule (constructed in declaration order, destroyed in reverse), which is what lets RAII release the last thing acquired first.
What is a virtual function and how does runtime polymorphism work in C++?
A function a derived class can override, where the version that runs depends on the object's real type, not the pointer's.
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
struct Shape {
virtual double area() const = 0;
virtual ~Shape() = default;
};
struct Square : Shape {
double s;
Square(double s) : s(s) {}
double area() const override { return s * s; }
};
struct Circle : Shape {
double r;
Circle(double r) : r(r) {}
double area() const override { return 3.14 * r * r; }
};
int main() {
vector<unique_ptr<Shape>> shapes;
shapes.push_back(make_unique<Square>(2));
shapes.push_back(make_unique<Circle>(1));
for (const auto& s : shapes) cout << s->area() << "\n";
}This prints 4 and 3.14. Without virtual, the call binds at compile time to the pointer's type. Write override so a signature mismatch fails to compile. More in the virtual functions docs.
What does this print: a virtual and a non-virtual call through a base pointer?
#include <iostream>
using namespace std;
struct Animal {
void name() { cout << "Animal "; }
virtual void sound() { cout << "..."; }
};
struct Dog : Animal {
void name() { cout << "Dog "; }
void sound() override { cout << "Woof"; }
};
int main() {
Dog d;
Animal* p = &d;
p->name();
p->sound();
cout << "\n";
}Predict the output
It prints Animal Woof. name() is not virtual, so a call through an Animal* binds at compile time to Animal::name; Dog::name only hides it. sound() is virtual, so the call goes through the vtable to Dog::sound.
How do virtual functions work internally? Explain the vtable and vptr.
Each class with virtual functions gets one vtable, an array of function pointers, and each object carries a hidden vptr to it; a virtual call loads the vptr, indexes the table and calls. The standard does not require this, but every mainstream compiler does it.
#include <iostream>
struct Plain { void f() {} };
struct Virt { virtual void f() {} };
int main() {
std::cout << sizeof(Plain) << " " << sizeof(Virt) << "\n";
}On a 64-bit platform (GCC, Clang or MSVC) this prints 1 8: the vptr adds 8 bytes.
Why should a base class have a virtual destructor?
Deleting a derived object through a base pointer whose destructor is not virtual is undefined behavior; typically only the base destructor runs and whatever the derived class owns leaks.
#include <iostream>
using namespace std;
struct Base {
virtual ~Base() { cout << "~Base\n"; }
};
struct Derived : Base {
~Derived() override { cout << "~Derived\n"; }
};
int main() {
Base* p = new Derived;
delete p;
}With virtual it prints ~Derived then ~Base. A class never meant to be deleted through a base pointer can make its destructor protected and non-virtual instead.
What is a pure virtual function and an abstract class?
A pure virtual function is declared with = 0, and a class with one is abstract: only derived classes that override every pure virtual can be created. An interface is an abstract class with only pure virtuals and a virtual destructor.
class Logger {
public:
virtual void log(const std::string& msg) = 0;
virtual ~Logger() = default;
};
A pure virtual destructor must still have a body, because derived destructors call it.
What is the difference between function overloading and function overriding?
Overloading is several functions with one name and different parameters, resolved at compile time. Overriding is a derived class replacing a base virtual function with the same signature, resolved at runtime.
The trap: a derived function with the same name but different parameters hides the base version. Bring it back with using Base::f;.
What does this print: a derived object passed by value and by reference?
#include <iostream>
using namespace std;
struct Base {
virtual const char* who() const { return "Base"; }
virtual ~Base() = default;
};
struct Derived : Base {
const char* who() const override { return "Derived"; }
};
void byValue(Base b) { cout << b.who() << " "; }
void byRef(const Base& b) { cout << b.who() << "\n"; }
int main() {
Derived d;
byValue(d);
byRef(d);
}Predict the output
It prints Base Derived. Passing d by value to a Base parameter copies only the Base part, so the copy's vptr points at Base's vtable. Passing by reference keeps the real object, so the virtual call reaches Derived::who.
The same slicing happens in std::vector<Base>; store std::unique_ptr<Base> instead.
What is the diamond problem in C++ and how does virtual inheritance solve it?
When Copier derives from Scanner and Printer, which both derive from Device, it holds two Device subobjects and c.id is ambiguous. Virtual inheritance makes them share one.
#include <iostream>
using namespace std;
struct Device { int id = 7; };
struct Scanner : virtual Device {};
struct Printer : virtual Device {};
struct Copier : Scanner, Printer {};
int main() {
Copier c;
cout << c.id << "\n"; // one Device, so no ambiguity
}This prints 7. The most derived class constructs the shared base, so Copier chooses the Device(...) arguments.
What does this print: a virtual call from a base-class constructor?
#include <iostream>
using namespace std;
struct Base {
Base() { hello(); }
virtual void hello() { cout << "Base\n"; }
virtual ~Base() = default;
};
struct Derived : Base {
void hello() override { cout << "Derived\n"; }
};
int main() {
Derived d;
d.hello();
}Predict the output
It prints Base and then Derived. While Base's constructor runs, the object is only a Base and the vptr points at Base's vtable, so the call reaches Base::hello. After construction, d.hello() reaches Derived::hello.
Destructors behave the same way in reverse, and calling a pure virtual function this way is undefined behavior.
What is the difference between a shallow copy and a deep copy in C++?
A shallow copy copies the pointer, so two objects share memory; a deep copy allocates and copies the data. The default copy is shallow for raw pointers, so both destructors free one block.
#include <iostream>
#include <cstring>
class Buffer {
char* data;
public:
Buffer(const char* s) : data(new char[strlen(s) + 1]) { strcpy(data, s); }
Buffer(const Buffer& o) : data(new char[strlen(o.data) + 1]) { strcpy(data, o.data); }
Buffer& operator=(const Buffer& o) {
if (this != &o) {
char* fresh = new char[strlen(o.data) + 1];
strcpy(fresh, o.data);
delete[] data;
data = fresh;
}
return *this;
}
~Buffer() { delete[] data; }
void set(char c) { data[0] = c; }
const char* get() const { return data; }
};
int main() {
Buffer a("cat");
Buffer b = a;
b.set('b');
std::cout << a.get() << " " << b.get() << "\n";
}This prints cat bat. Holding a std::string instead makes the default copy deep (the rule of zero).
How does operator overloading work in C++? Which operators cannot be overloaded?
You define a function named operator+, operator==, operator<< and so on; at least one operand must be a user-defined type.
#include <iostream>
using namespace std;
struct Vec2 {
int x, y;
Vec2 operator+(const Vec2& o) const { return {x + o.x, y + o.y}; }
friend ostream& operator<<(ostream& os, const Vec2& v) {
return os << "(" << v.x << ", " << v.y << ")";
}
};
int main() {
Vec2 a{1, 2}, b{3, 4};
cout << a + b << "\n";
}This prints (4, 6). operator<< is a non-member friend because its left operand is the stream. You cannot overload ::, ., .*, ?:, sizeof, alignof or typeid. See the operator overloading docs.
What is a friend function in C++?
A non-member function that a class allows to access its private and protected members; a whole class can be a friend too.
#include <iostream>
using namespace std;
class Box {
double width;
public:
Box(double w) : width(w) {}
friend void show(const Box& b); // not a member, but sees width
friend class Inspector;
};
void show(const Box& b) { cout << "width " << b.width << "\n"; }
class Inspector {
public:
static double twice(const Box& b) { return b.width * 2; }
};
int main() {
Box b(3.5);
show(b);
cout << Inspector::twice(b) << "\n";
}This prints width 3.5 and then 7. Friendship is not inherited, mutual or transitive. The usual use is operator<<.
Can a constructor be virtual in C++?
No. A virtual call needs the vptr, which the constructor itself sets up, and when you create an object you already name its exact type. To copy an object you hold only through a base pointer, use a virtual clone().
#include <iostream>
#include <memory>
using namespace std;
struct Shape {
virtual unique_ptr<Shape> clone() const = 0;
virtual const char* name() const = 0;
virtual ~Shape() = default;
};
struct Circle : Shape {
unique_ptr<Shape> clone() const override { return make_unique<Circle>(*this); }
const char* name() const override { return "Circle"; }
};
int main() {
unique_ptr<Shape> a = make_unique<Circle>();
unique_ptr<Shape> b = a->clone();
cout << b->name() << " " << (a.get() != b.get()) << "\n";
}This prints Circle 1: a new, separate Circle.
What is the difference between public, protected and private inheritance?
The mode caps how visible the base's members are in the derived class: public keeps them, protected makes public members protected, private makes both private. Base private members are never accessible.
Only public inheritance models "is a", so Derived* converts to Base* for any caller. See the access specifiers docs.
C++ pointers and references interview questions
Pointer arithmetic, references, const with pointers, nullptr and dangling pointers.
What is the difference between a pointer and a reference in C++?
A reference is another name for an existing object; a pointer is a variable holding an address. A pointer can be null, re-pointed and used in arithmetic; a reference is bound once, at initialization.
Take const T& or T& when an object must exist, and a pointer when "no object" is valid. See references vs pointers.
What does this print: an int changed by value, by reference and through a pointer?
#include <iostream>
using namespace std;
void byValue(int x) { x = 10; }
void byRef(int& x) { x = 20; }
void byPtr(int* x) { *x = 30; }
int main() {
int a = 1, b = 1, c = 1;
byValue(a);
byRef(b);
byPtr(&c);
cout << a << " " << b << " " << c << "\n";
}Predict the output
It prints 1 20 30. byValue changes a copy, byRef changes b itself, and byPtr writes through the address of c.
Pass small types by value, large read-only objects by const T&, objects you modify by T&, and a pointer when the argument may be absent.
What does this print: assigning another variable to a reference?
#include <iostream>
using namespace std;
int main() {
int a = 1, b = 2;
int& r = a;
r = b;
r = 3;
cout << a << " " << b << "\n";
}Predict the output
It prints 3 2. A reference cannot be re-pointed: r = b; assigns the value of b (2) to a, and r = 3; assigns 3 to a. b is never touched.
If you need a rebindable reference, for example inside a container, use a pointer or std::reference_wrapper.
What does this print: pointer arithmetic on an int array?
#include <iostream>
using namespace std;
int main() {
int a[] = {10, 20, 30, 40};
int* p = a;
p += 2;
cout << *p << " " << p[-1] << " " << (p - a) << "\n";
}Predict the output
It prints 30 20 2. Pointer arithmetic counts in elements, so p += 2 moves to a[2], p[-1] is a[1], and p - a is the number of elements between them.
Moving a pointer outside the array (past one-past-the-end) is undefined behavior even without a dereference.
What is the difference between const int*, int* const and const int* const?
Read the declaration from right to left:
const int* p: pointer to a const int. You can movep, not change*p.int* const p: const pointer. You can change*p, notp.const int* const p: neither can change.
int x = 1, y = 2;
const int* a = &x; a = &y; // ok
// *a = 5; error: *a is const
int* const b = &x; *b = 5; // ok
// b = &y; error: b is const
What is the difference between nullptr and NULL?
nullptr (C++11) converts to any pointer type but never to an integer. NULL is a C macro, 0 on MSVC and the integer constant __null on GCC and Clang with glibc.
#include <iostream>
void f(int) { std::cout << "f(int)\n"; }
void f(int*) { std::cout << "f(int*)\n"; }
int main() {
f(0);
f(nullptr);
}This prints f(int) and then f(int*). f(NULL) calls f(int) on MSVC, is ambiguous with glibc, and calls f(int*) with musl (this page's runner).
What is a dangling pointer, and how do you avoid it?
A pointer or reference to an object that no longer exists; using it is undefined behavior.
int* p = new int(5);
delete p; // p now dangles
*p = 6; // undefined behavior
int& bad() {
int local = 42;
return local; // reference to a destroyed local
}
std::vector<int> v = {1, 2, 3};
int* first = &v[0];
v.push_back(4); // may reallocate: first can dangle
Avoid it with owning types (std::unique_ptr, containers), by returning by value, and by not keeping pointers into a vector across push_back. AddressSanitizer catches most cases.
What is the this pointer in C++?
A pointer, inside every non-static member function, to the object the function was called on. It separates a member from a parameter (this->x = x;) and lets a method return *this so calls chain.
#include <iostream>
#include <string>
using namespace std;
class Query {
string sql = "SELECT *";
public:
Query& from(const string& t) { sql += " FROM " + t; return *this; }
Query& where(const string& c) { sql += " WHERE " + c; return *this; }
string str() const { return sql; }
};
int main() {
cout << Query().from("users").where("age > 18").str() << "\n";
}This prints SELECT * FROM users WHERE age > 18. In a const member function this points to const.
C++ memory management and smart pointers interview questions
new and delete, stack vs heap, leaks, RAII and the three smart pointers.
What is the difference between new/delete and malloc/free?
new allocates memory and runs the constructor, and delete runs the destructor before freeing; malloc and free only handle raw bytes. new is also type safe and throws std::bad_alloc on failure, where malloc returns NULL.
Mixing them (new with free, new[] with delete) is undefined behavior.
What is the difference between stack and heap memory in C++?
Local variables live on the stack and are destroyed when their scope ends; objects from new live on the heap until freed. The stack is fast but small, so deep recursion overflows it: 1 MB by default on Windows (see the /STACK linker option) and usually 8 MB on Linux. The heap is larger and slower, and its bugs are leaks and use after free. std::vector<int> v(1000000); puts the vector object on the stack and its ints on the heap.
What is the difference between delete and delete[]?
delete p destroys one object from new; delete[] p destroys an array from new T[n], calling every element's destructor. The wrong form is undefined behavior: for elements with a destructor the compiler usually stores the count before the array, and only delete[] reads it. Prefer std::vector or std::make_unique<int[]>(n).
What is a memory leak in C++, and how do you find and prevent one?
Heap memory that is never freed, because nothing points to it any more or the code that frees it never runs. Typical causes are new without delete on an exception path, a missing virtual destructor, and shared_ptr cycles.
Find leaks with Valgrind or AddressSanitizer. Prevent them with RAII: containers and std::unique_ptr instead of raw new.
What is RAII in C++?
RAII ties a resource to an object's lifetime: the constructor acquires it (memory, a file, a mutex) and the destructor releases it. Destructors run at scope end, including during stack unwinding, so release is guaranteed.
#include <iostream>
#include <stdexcept>
using namespace std;
struct File {
File() { cout << "open\n"; }
~File() { cout << "close\n"; }
};
void work() {
File f;
throw runtime_error("disk full");
}
int main() {
try {
work();
} catch (const exception& e) {
cout << "caught: " << e.what() << "\n";
}
}This prints open, close, then caught: disk full. std::vector, std::unique_ptr and std::lock_guard work this way, which is why C++ has no finally.
What are smart pointers in C++? Explain unique_ptr, shared_ptr and weak_ptr.
RAII wrappers that delete the object they own. std::unique_ptr has one owner, can only be moved and costs nothing extra. std::shared_ptr shares ownership through a reference count. std::weak_ptr observes a shared_ptr without owning it.
#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main() {
auto p = make_unique<string>("hi");
auto q = std::move(p); // ownership moves, p becomes empty
cout << (p ? "p owns" : "p is empty") << ", q = " << *q << "\n";
}This prints p is empty, q = hi. Default to unique_ptr. More in the smart pointers docs.
What does this print: use_count() with copies in a nested scope and a weak_ptr?
#include <iostream>
#include <memory>
using namespace std;
int main() {
auto a = make_shared<int>(42);
auto b = a;
{
auto c = a;
cout << a.use_count() << " ";
}
weak_ptr<int> w = a;
cout << a.use_count() << "\n";
}Predict the output
What is a shared_ptr reference cycle and how does weak_ptr fix it?
Why prefer std::make_shared over std::shared_ptr<T>(new T)?
C++ STL interview questions
Which container to pick, what each operation costs, and the traps in map, vector and remove.
What is the STL and what are its main components?
The generic part of the standard library: containers (vector, map, unordered_map...), container adaptors (stack, queue, priority_queue), iterators, algorithms (sort, find, accumulate) and function objects such as lambdas. Algorithms work on iterator ranges, not on containers.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {5, 2, 9, 1};
sort(v.begin(), v.end());
auto it = find(v.begin(), v.end(), 9);
cout << "sorted: ";
for (int x : v) cout << x << " ";
cout << "| 9 at index " << (it - v.begin()) << "\n";
}This prints sorted: 1 2 5 9 | 9 at index 3.
What is the difference between vector, list and deque?
vector | deque | list | |
|---|---|---|---|
| Random access | O(1) | O(1) | no |
| Insert at front | O(n) | O(1) | O(1) |
| Insert in middle | O(n) | O(n) | O(1) with an iterator |
All three add at the end in amortized O(1). Default to vector: one contiguous block beats list even for many middle insertions, because walking a list costs a cache miss per node. Use deque for both ends and list for stable iterators.
What is the difference between map and unordered_map in C++?
std::map keeps sorted keys in a balanced binary search tree (red-black in the major libraries) with O(log n) operations. std::unordered_map is a hash table with no order, O(1) on average and O(n) in the worst case.
Use unordered_map for plain lookups and map for sorted output or lower_bound queries. The hash table visualization shows buckets and collisions.
What does this print: iterating a std::map filled in non-alphabetical order?
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> m;
m["pear"] = 3;
m["apple"] = 5;
m["fig"] = 1;
m["apple"] += 1;
for (auto& [k, v] : m) cout << k << "=" << v << " ";
cout << "\n";
}Predict the output
It prints apple=6 fig=1 pear=3. std::map keeps its keys sorted, so iteration is alphabetical whatever the insertion order, and m["apple"] += 1 adds to the existing value. With std::unordered_map the order would be unspecified.
What does this print: reading a missing key with map::operator[]?
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> m;
if (m["missing"] == 0) cout << "zero ";
cout << m.size() << "\n";
}Predict the output
It prints zero 1. operator[] inserts a value-initialized element when the key is missing, so reading m["missing"] adds the key with value 0.
To look up without inserting, use m.find(key), m.count(key), m.at(key) (throws if missing) or C++20's m.contains(key).
How does std::vector grow? What is the difference between size and capacity?
size() is how many elements the vector holds; capacity() is how many fit before it must reallocate. When full, it allocates a block a constant factor larger and moves the elements, so push_back is amortized O(1).
#include <iostream>
#include <vector>
int main() {
std::vector<int> v;
size_t last = 0;
for (int i = 0; i < 20; ++i) {
v.push_back(i);
if (v.capacity() != last) {
last = v.capacity();
std::cout << last << " ";
}
}
std::cout << "\n";
}With GCC's libstdc++ this prints 1 2 4 8 16 32; MSVC grows by 1.5 times. Reallocation invalidates every pointer and iterator. See the vector docs.
What is iterator invalidation? How do you erase from a container while iterating?
When a container change leaves an iterator pointing at freed or moved memory; using it is undefined behavior. A vector reallocation invalidates all iterators; in list, map and set only the erased element's. To erase while iterating, continue from the iterator erase returns.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5, 6};
for (auto it = v.begin(); it != v.end(); ) {
if (*it % 2 == 0) it = v.erase(it);
else ++it;
}
for (int x : v) cout << x << " ";
cout << "\n";
}This prints 1 3 5. More in the iterators docs.
What does this print: vector size after std::remove and then erase?
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 2, 4, 2};
auto newEnd = remove(v.begin(), v.end(), 2);
cout << v.size() << " ";
v.erase(newEnd, v.end());
cout << v.size() << "\n";
}Predict the output
It prints 6 3. std::remove only sees iterators, so it cannot change the size: it shifts the kept elements (1, 3, 4) to the front and returns the new logical end. erase then cuts the leftover tail.
Together that is the erase-remove idiom, v.erase(remove(v.begin(), v.end(), 2), v.end());. C++20's std::erase(v, 2) and std::erase_if do both steps.
What does this print: top() of a default priority_queue and one with greater<int>?
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() {
priority_queue<int> maxq;
priority_queue<int, vector<int>, greater<int>> minq;
for (int x : {4, 1, 7, 3}) {
maxq.push(x);
minq.push(x);
}
cout << maxq.top() << " " << minq.top() << "\n";
}Predict the output
It prints 7 1. std::priority_queue is a max-heap by default. For a min-heap pass std::greater<int> as the third template argument, which means also naming the container, vector<int>, as the second.
push and pop are O(log n) and top is O(1). The heap visualization shows a min-heap sifting each value up.
Which algorithm does std::sort use, and how do you sort with a custom comparator?
Introsort in GCC's libstdc++ and MSVC (quicksort falling back to heapsort, insertion sort for small ranges), with O(n log n) guaranteed since C++11. It is not stable; use std::stable_sort for that.
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<pair<int, int>> intervals = {{5, 7}, {1, 3}, {2, 4}, {1, 2}};
sort(intervals.begin(), intervals.end(), [](const auto& a, const auto& b) {
if (a.first != b.first) return a.first < b.first;
return a.second < b.second;
});
for (auto& [s, e] : intervals) cout << "[" << s << "," << e << "] ";
cout << "\n";
}This prints [1,2] [1,3] [2,4] [5,7]. The comparator must be a strict weak ordering, so <= is undefined behavior. The quicksort visualization shows the partition step.
What is the difference between push_back and emplace_back?
push_back copies or moves an existing object into the vector. emplace_back takes constructor arguments and builds the element in place.
#include <iostream>
#include <vector>
using namespace std;
struct P {
P(int, int) { cout << "ctor "; }
P(const P&) { cout << "copy "; }
P(P&&) noexcept { cout << "move "; }
};
int main() {
vector<P> v;
v.reserve(2);
v.push_back(P(1, 2));
v.emplace_back(3, 4);
cout << "\n";
}This prints ctor move ctor . The trap: emplace_back calls explicit constructors, so v.emplace_back(10) on a vector<vector<int>> adds a vector of ten zeros where push_back(10) would not compile.
What does this print: a std::set built from a vector with duplicates?
#include <iostream>
#include <set>
#include <vector>
using namespace std;
int main() {
vector<int> v = {3, 1, 3, 2, 1};
set<int> s(v.begin(), v.end());
cout << s.size() << " " << *s.begin() << " " << *s.rbegin() << "\n";
}Predict the output
It prints 3 1 3. A std::set keeps one copy of each value and stays sorted, so it holds {1, 2, 3}, *s.begin() is 1 and *s.rbegin() is 3.
When order does not matter, std::unordered_set gives O(1) average lookups instead of O(log n).
What are std::stack and std::queue, and what are container adaptors?
std::stack (last in, first out) and std::queue (first in, first out) are container adaptors: they wrap another container, std::deque by default, and expose only push, pop, top or front, empty and size. They cannot be iterated, and pop() returns void, so read top() first.
#include <iostream>
#include <stack>
#include <string>
using namespace std;
bool balanced(const string& s) {
stack<char> st;
for (char c : s) {
if (c == '(' || c == '[' || c == '{') { st.push(c); continue; }
if (st.empty()) return false;
char open = st.top();
st.pop();
if ((c == ')' && open != '(') || (c == ']' && open != '[') || (c == '}' && open != '{'))
return false;
}
return st.empty();
}
int main() {
cout << balanced("{[()]}") << " " << balanced("([)]") << "\n";
}This prints 1 0.
C++ templates interview questions
Function and class templates, specialization, SFINAE, concepts and variadic templates.
What are templates in C++?
A template is a blueprint the compiler uses to generate a separate, fully typed function or class for each type you use it with, at compile time.
#include <iostream>
#include <string>
using namespace std;
template <typename T>
T maxOf(T a, T b) {
return a > b ? a : b;
}
int main() {
cout << maxOf(3, 7) << " " << maxOf(2.5, 1.5) << " "
<< maxOf<string>("pear", "apple") << "\n";
}This prints 7 2.5 pear. Without the explicit <string>, the arguments would be two const char* and > would compare addresses. See the templates docs.
How do you write a class template? Give an example.
Put template <typename T> before the class and use T wherever the type varies; each Stack<int> or Stack<std::string> is a separate class.
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
using namespace std;
template <typename T>
class Stack {
vector<T> items;
public:
void push(const T& x) { items.push_back(x); }
T pop() {
if (items.empty()) throw out_of_range("empty stack");
T top = items.back();
items.pop_back();
return top;
}
bool empty() const { return items.empty(); }
};
int main() {
Stack<string> s;
s.push("a");
s.push("b");
cout << s.pop() << s.pop() << " " << s.empty() << "\n";
}This prints ba 1 (since C++17 the two s.pop() calls in one << chain run left to right; see the evaluation order rules). Members are instantiated only when used.
What does this print: a class template with a full and a partial specialization?
#include <iostream>
using namespace std;
template <typename T>
struct TypeName { static const char* get() { return "unknown"; } };
template <>
struct TypeName<int> { static const char* get() { return "int"; } };
template <typename T>
struct TypeName<T*> { static const char* get() { return "pointer"; } };
int main() {
cout << TypeName<int>::get() << " "
<< TypeName<double*>::get() << " "
<< TypeName<char>::get() << "\n";
}Predict the output
It prints int pointer unknown. The compiler picks the most specialized match: int uses the full specialization, double* the partial specialization for T*, and char the primary template.
Only class and variable templates can be partially specialized; function templates are overloaded instead. Type traits such as std::is_pointer are built this way.
Why are templates usually defined in header files?
The compiler needs the full definition where the template is used, to generate code for that type. Defined only in stack.cpp, Stack<int>::push is never generated and the linker reports an undefined reference. Explicit instantiations in the .cpp are the alternative, limiting users to those types.
// stack.cpp
template class Stack<int>;
template class Stack<std::string>;
What is SFINAE, and how do C++20 concepts replace it?
SFINAE ("substitution failure is not an error"): if substituting template arguments into a signature produces invalid code, that template is dropped from overload resolution instead of causing an error. std::enable_if uses it to switch overloads by type.
#include <iostream>
#include <type_traits>
template <typename T>
std::enable_if_t<std::is_integral_v<T>, const char*> kind(T) { return "integer"; }
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, const char*> kind(T) { return "floating"; }
int main() {
std::cout << kind(5) << " " << kind(2.0) << "\n";
}This prints integer floating. C++20 concepts say the same directly, with readable errors.
template <std::integral T>
const char* kind(T) { return "integer"; }
template <std::floating_point T>
const char* kind(T) { return "floating"; }
What are variadic templates and fold expressions?
A variadic template takes any number of arguments through a parameter pack (typename... Args). C++17 fold expressions apply an operator across the pack without recursion.
#include <iostream>
template <typename... Args>
auto sum(Args... args) {
return (args + ...);
}
template <typename... Args>
void printAll(const Args&... args) {
((std::cout << args << " "), ...);
std::cout << "\n";
}
int main() {
std::cout << sum(1, 2, 3, 4) << "\n";
printAll(1, "two", 3.0);
}This prints 10, then 1 two 3 (3.0 prints as 3). sizeof...(args) gives the pack's size. std::make_unique and emplace_back use variadic templates with perfect forwarding.
What is the difference between templates and macros?
Macros are text substitution by the preprocessor; templates are part of the language and are type checked by the compiler. Macros also ignore scope and may evaluate an argument twice.
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int i = 5;
int m = MAX(i++, 3); // i++ runs twice: i ends at 7
template <typename T>
T max2(T a, T b) { return a > b ? a : b; }
Use templates or constexpr functions for code, and keep macros for include guards, conditional compilation and __FILE__/__LINE__ in logging.
Modern C++ interview questions (C++11, 14, 17, 20)
auto, lambdas, move semantics, perfect forwarding, constexpr and C++17 and C++20 features.
What are the main features added in C++11, C++14, C++17 and C++20?
| Standard | Headline features |
|---|---|
| C++11 | auto, lambdas, move semantics, smart pointers, nullptr, range-based for, constexpr, std::thread |
| C++14 | std::make_unique, generic lambdas |
| C++17 | structured bindings, std::optional, std::string_view, if constexpr, guaranteed copy elision |
| C++20 | concepts, ranges, coroutines, modules, <=>, std::format |
| C++23 | std::expected, std::print |
What does this print: auto and auto& initialized from a reference?
#include <iostream>
using namespace std;
int main() {
int x = 5;
int& r = x;
auto a = r;
auto& b = r;
a = 100;
b = 7;
cout << x << "\n";
}Predict the output
It prints 7. auto drops the reference, so a is a copy and a = 100 does not touch x. auto& b = r; keeps the reference, so b = 7 changes x.
The same rule makes for (auto s : names) copy every string; write const auto&.
What is a lambda expression in C++?
An anonymous function object written inline, usually to pass to an algorithm: [capture](parameters) { body }.
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {7, -2, 9, 4, -5};
int limit = 5;
auto above = count_if(v.begin(), v.end(), [limit](int x) { return x > limit; });
sort(v.begin(), v.end(), [](int a, int b) { return abs(a) < abs(b); });
cout << above << " | ";
for (int x : v) cout << x << " ";
cout << "\n";
}This prints 2 | -2 4 -5 7 9. The compiler generates a class with an operator(), and captures become its members. Store a lambda in auto, or in std::function when you need one fixed type.
What does this print: a lambda capture by value and by reference after the variable changes?
#include <iostream>
using namespace std;
int main() {
int x = 1;
auto byVal = [x]() { return x; };
auto byRef = [&x]() { return x; };
x = 5;
cout << byVal() << " " << byRef() << "\n";
}Predict the output
It prints 1 5. [x] stores a copy of x when the lambda is created; [&x] reads the current value.
A by-value capture is const inside the lambda unless you add mutable, and a by-reference capture that outlives the variable dangles. More in the lambdas docs.
What are move semantics and rvalue references?
An rvalue reference T&& binds to temporaries, so a class can define a move constructor that steals a temporary's resources instead of copying them.
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main() {
std::vector<std::string> v;
std::string s = "a long string that does not fit in the small buffer";
v.push_back(s); // copy: s keeps its text
v.push_back(std::move(s)); // move: v takes s's buffer
std::cout << v.size() << " [" << s << "]\n";
}With GCC this prints 2 []. A moved-from object is "valid but unspecified", so do not rely on its value. Mark move constructors noexcept, or containers copy instead.
What does std::move actually do? What is perfect forwarding?
std::move moves nothing: it casts to an rvalue reference so overload resolution picks the move constructor. Perfect forwarding passes an argument on with its original value category: in a template T&& is a forwarding reference, and std::forward<T>(arg) restores it.
#include <iostream>
#include <string>
#include <utility>
using namespace std;
void take(const string&) { cout << "lvalue\n"; }
void take(string&&) { cout << "rvalue\n"; }
template <typename T>
void relay(T&& arg) {
take(std::forward<T>(arg));
}
int main() {
string s = "x";
relay(s);
relay(string("y"));
relay(std::move(s));
}This prints lvalue, rvalue, rvalue. Without std::forward all three print lvalue, because a named parameter is an lvalue.
How do std::optional and structured bindings (C++17) make code clearer?
std::optional<T> holds a T or nothing, replacing sentinels like -1. Structured bindings unpack pairs, tuples and structs into named variables.
#include <iostream>
#include <map>
#include <optional>
#include <string>
using namespace std;
optional<int> findAge(const map<string, int>& ages, const string& name) {
if (auto it = ages.find(name); it != ages.end()) return it->second;
return nullopt;
}
int main() {
map<string, int> ages = {{"ana", 31}, {"raj", 27}};
for (const auto& [name, age] : ages) cout << name << ":" << age << " ";
cout << "\n";
cout << findAge(ages, "raj").value_or(-1) << " "
<< findAge(ages, "zoe").has_value() << "\n";
}This prints ana:31 raj:27 and then 27 0. The if (auto it = ...; cond) form, also C++17, keeps it scoped to the if.
What is constexpr, and how is it different from const?
const means the value does not change after initialization, which may happen at runtime. constexpr means it can be evaluated at compile time; a constexpr function is guaranteed to run at compile time only where a constant is required, such as a constexpr variable, static_assert or an array size.
#include <iostream>
constexpr long long factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
static_assert(factorial(5) == 120);
constexpr auto f10 = factorial(10);
int n = 6;
std::cout << f10 << " " << factorial(n) << "\n";
}This prints 3628800 720: f10 was computed by the compiler, factorial(n) at runtime. C++20 adds consteval, which must run at compile time. See the constexpr reference.
What do concepts, ranges and the spaceship operator in C++20 look like?
These are shown as plain code because this page's runner compiles C++17; use g++ -std=c++20.
#include <compare>
#include <concepts>
#include <ranges>
#include <vector>
// Concepts: constrain a template, with readable errors
template <std::integral T>
T half(T x) { return x / 2; }
// Three-way comparison: one defaulted operator gives ==, !=, <, <=, >, >=
struct Version {
int major, minor;
auto operator<=>(const Version&) const = default;
};
// Ranges: lazy, composable views instead of iterator pairs
std::vector<int> v = {1, 2, 3, 4, 5, 6};
auto squaresOfEvens = v
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; }); // 4 16 36
C++20 also brought coroutines, modules, std::format and std::span.
C++ interview questions for experienced developers (5 to 10 years)
Undefined behavior, the rule of five, copy elision, exception safety, concurrency and design idioms.
What is undefined behavior in C++? Give examples.
Code the standard places no requirements on. The compiler may assume it never happens and optimize on that, so the program can work, crash, or change at another optimization level.
Examples: reading an uninitialized variable, signed overflow (unsigned wraps), out-of-bounds access, a dangling or null dereference, data races. Catch it with -fsanitize=undefined,address. More in the undefined behavior docs.
What are the rule of three, the rule of five and the rule of zero?
- Three: a class needing a custom destructor, copy constructor or copy assignment needs all three.
- Five (C++11): add the two move operations; declaring a copy operation or destructor suppresses the implicit moves.
- Zero: define none, and hold resources in members that manage themselves.
class Good { // rule of zero
std::string name;
std::vector<int> data;
std::unique_ptr<Impl> impl; // move only, so Good is move only
};
class NonCopyable {
public:
NonCopyable() = default; // declaring a copy constructor removes the implicit default one
NonCopyable(const NonCopyable&) = delete;
NonCopyable& operator=(const NonCopyable&) = delete;
};
What does this print: returning a temporary from a function with copy and move constructors that log?
#include <iostream>
using namespace std;
struct Widget {
Widget() { cout << "ctor "; }
Widget(const Widget&) { cout << "copy "; }
Widget(Widget&&) noexcept { cout << "move "; }
};
Widget make() { return Widget(); }
int main() {
Widget w = make();
cout << "\n";
}Predict the output
It prints ctor. Since C++17, returning and initializing from a prvalue is guaranteed copy elision: the object is built directly in w, so neither copy nor move runs.
For a named local (Widget w; return w;), elision (NRVO) is allowed but not guaranteed, with a move as the fallback. return std::move(w); blocks NRVO. See the copy elision rules.
What does this print: vector reallocation with a move constructor that is not noexcept?
#include <iostream>
#include <vector>
using namespace std;
struct Item {
Item() {}
Item(const Item&) { cout << "copy "; }
Item(Item&&) { cout << "move "; } // not noexcept
};
int main() {
vector<Item> v;
v.reserve(1);
v.emplace_back();
v.emplace_back();
cout << "\n";
}Predict the output
It prints copy. The second emplace_back reallocates, and the vector must keep the strong exception guarantee. A move that might throw could leave the old buffer half emptied, so the vector uses std::move_if_noexcept and copies.
Add noexcept to Item(Item&&) and it prints move. Make move operations noexcept whenever they cannot fail.
What are the exception safety guarantees in C++?
Three levels: basic (nothing leaks, the object stays valid), strong (success or no effect, like vector::push_back) and no-throw (noexcept, expected of destructors, swap and moves). Copy and swap gives assignment the strong guarantee.
Buffer& operator=(Buffer other) { // copy made here; may throw
swap(*this, other); // noexcept
return *this; // old data freed with other
}
What are the four C++ casts, and when do you use each one?
| Cast | Use |
|---|---|
static_cast | numbers, known up and down casts; a wrong downcast is UB |
dynamic_cast | downcast checked at runtime in a polymorphic hierarchy |
const_cast | add or remove const |
reinterpret_cast | reinterpret bits, unchecked |
#include <iostream>
#include <memory>
using namespace std;
struct Shape { virtual ~Shape() = default; };
struct Circle : Shape { double r = 2; };
struct Square : Shape {};
int main() {
unique_ptr<Shape> s = make_unique<Circle>();
if (auto c = dynamic_cast<Circle*>(s.get())) cout << "circle r=" << c->r << "\n";
cout << (dynamic_cast<Square*>(s.get()) == nullptr) << "\n";
}This prints circle r=2 and then 1: a failed dynamic_cast to a pointer gives nullptr. Avoid C-style casts, which may silently become reinterpret_cast.
How do you avoid data races in C++? Compare std::mutex and std::atomic.
A data race (two threads, one variable, at least one writing, no synchronization) is undefined behavior. Protect shared data with a std::mutex, or make a single variable std::atomic.
#include <atomic>
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
int main() {
std::atomic<int> hits{0};
int total = 0; // guarded by m
std::mutex m;
auto work = [&] {
for (int i = 0; i < 100000; ++i) {
++hits;
std::lock_guard<std::mutex> lock(m);
++total;
}
};
std::vector<std::thread> threads;
for (int i = 0; i < 4; ++i) threads.emplace_back(work);
for (auto& t : threads) t.join();
std::cout << hits << " " << total << "\n";
}This prints 400000 400000. Use atomic for one counter or flag and a mutex, locked through lock_guard, when several values change together.
What does the explicit keyword do?
explicit on a constructor stops the compiler from using it for implicit conversions, so a function taking Meters cannot silently accept a double.
#include <iostream>
using namespace std;
struct Meters {
double value;
explicit Meters(double v) : value(v) {}
};
void run(Meters m) { cout << "ran " << m.value << " m\n"; }
int main() {
run(Meters(5));
// run(5); does not compile: no implicit double to Meters
// Meters m = 5; does not compile either
}This prints ran 5 m. Make single-argument constructors explicit by default.
What is a const member function, and what is mutable for?
A const member function promises not to change the object's observable state, and it is the only kind callable on a const object or through a const&. mutable marks a member that a const function may still change, such as a cache or a mutex.
#include <iostream>
#include <string>
using namespace std;
class Report {
string text;
mutable int reads = 0;
public:
Report(string t) : text(t) {}
const string& get() const { ++reads; return text; }
int count() const { return reads; }
};
int main() {
const Report r("Q3");
r.get();
r.get();
cout << r.get() << " read " << r.count() << " times\n";
}This prints Q3 read 3 times; without mutable, get() would not compile.
What is the static initialization order fiasco and how do you avoid it?
Globals in different translation units are initialized in an unspecified order, so one global's constructor may use another before it exists, depending on link order. The fix is a function-local static ("construct on first use"), initialized on the first call and thread safe since C++11.
std::string& appName() {
static std::string name = "coddy";
return name;
}
constexpr or C++20 constinit values avoid the problem too.
What does this print: v.size() - 1 on an empty vector?
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
cout << (v.size() - 1 > 0 ? "positive" : "not positive") << "\n";
}Predict the output
It prints positive. v.size() is an unsigned size_t, so 0 - 1 wraps to its largest value.
The same bug makes for (size_t i = 0; i < v.size() - 1; ++i) run far out of bounds on an empty vector. Write i + 1 < v.size().
What is the Pimpl idiom and why is it used?
Pimpl ("pointer to implementation") moves a class's private data into a struct defined only in the .cpp file; the header holds a pointer to it.
// widget.h
class Widget {
public:
Widget();
~Widget(); // defined in widget.cpp
void draw();
private:
struct Impl; // forward declaration only
std::unique_ptr<Impl> impl;
};
// widget.cpp
struct Widget::Impl { BigLibrary::Canvas canvas; int zoom = 1; };
Widget::Widget() : impl(std::make_unique<Impl>()) {}
Widget::~Widget() = default; // Impl is complete here
Private changes then do not touch the header, so dependents do not recompile and the ABI stays stable. The cost is a heap allocation and an indirection.
Preparing for the interview
How should I prepare for a C++ interview?
vector, unordered_map and sort come without thinking, and explaining out loud why code prints what it prints.What C++ topics are asked in interviews for freshers?
new vs malloc, static and const, and simple output questions. Expect one or two coding problems on arrays, strings or linked lists, usually written with the STL.What is asked in a C++ interview for 5 years of experience?
noexcept, smart pointer ownership, the rule of five, undefined behavior, iterator invalidation, exception safety, templates, and std::mutex vs std::atomic. You will also defend choices in your own code, such as a container or how you found a leak.Do I need DSA for a C++ developer interview?
Which C++ standard should I know for interviews?
auto) and the common C++17 additions (structured bindings, std::optional, if constexpr). Be able to describe C++20 concepts, ranges and <=>, and ask which standard the company's codebase uses.