Top Interview Questions
C++ is a high-level, general-purpose programming language that extends the capabilities of the C programming language. It was created by Bjarne Stroustrup in 1979 at Bell Labs as an enhancement to C, aiming to introduce object-oriented programming (OOP) features while retaining the efficiency and flexibility of C. Over the years, C++ has evolved through multiple standards, including C++98, C++03, C++11, C++14, C++17, C++20, and the upcoming C++23, each introducing new features to meet the demands of modern software development.
C++ is widely recognized for its performance, versatility, and rich feature set. Some of its key characteristics include:
Object-Oriented Programming (OOP):
C++ supports the four pillars of OOP: Encapsulation, Abstraction, Inheritance, and Polymorphism. This allows developers to model real-world problems using objects and classes, making code more modular, reusable, and easier to maintain.
Performance and Efficiency:
C++ allows direct manipulation of hardware resources through pointers and memory management, making it ideal for performance-critical applications such as game engines, operating systems, and real-time simulations.
Low-Level Manipulation:
Unlike many high-level languages, C++ allows low-level operations like direct memory access, pointer arithmetic, and hardware interfacing, giving developers complete control over system resources.
Portability:
C++ is a cross-platform language, meaning programs written in C++ can run on multiple operating systems with minimal modification, provided proper compilers are used.
Rich Standard Library (STL):
The Standard Template Library (STL) provides pre-defined data structures (like vectors, lists, and maps) and algorithms (like sort, search, and transform), reducing development time and promoting code reliability.
Multiple Paradigms:
C++ supports procedural, object-oriented, and generic programming, allowing developers to choose the best approach depending on the application’s requirements.
A typical C++ program consists of header files, functions, classes, and the main function. For example:
#include <iostream>
using namespace std;
class Student {
public:
string name;
int age;
void display() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
Student s1;
s1.name = "Yash";
s1.age = 24;
s1.display();
return 0;
}
This simple example demonstrates classes, objects, member functions, and basic input/output, which are the foundation of C++ programming.
Classes and Objects:
Classes act as blueprints for objects, encapsulating data members (attributes) and member functions (methods). Objects are instances of classes.
Encapsulation:
By restricting access to the internal state of objects using private and protected access specifiers, encapsulation helps safeguard data and prevents unintended modifications.
Inheritance:
C++ supports single, multiple, and multilevel inheritance, allowing one class to inherit properties and behaviors from another, promoting code reuse.
Polymorphism:
Polymorphism allows objects to behave differently depending on the context. It is implemented through function overloading, operator overloading, and virtual functions.
Abstraction:
Abstraction hides complex implementation details from the user and exposes only the necessary interface. This can be achieved using abstract classes and pure virtual functions.
C++ provides manual memory management using the new and delete operators, which allows precise control over resource allocation. This feature is crucial for applications requiring high performance or real-time processing, but it also demands careful handling to prevent memory leaks or dangling pointers.
Example:
int* ptr = new int(5); // allocate memory
cout << *ptr << endl; // use memory
delete ptr; // deallocate memory
C++ supports templates, which allow writing generic code for functions and classes. Templates are heavily used in the STL and enable code reuse without sacrificing type safety.
Example:
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
cout << add<int>(5, 10) << endl; // 15
cout << add<double>(5.5, 2.5) << endl; // 8.0
}
The STL is a collection of generic classes and functions, divided into:
Containers: Store data efficiently (e.g., vector, list, deque, map, set).
Algorithms: Perform operations on containers (e.g., sort, find, reverse).
Iterators: Provide a unified way to access elements in containers.
Example using STL:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> numbers = {5, 2, 8, 1};
sort(numbers.begin(), numbers.end());
for(int n : numbers) cout << n << " "; // 1 2 5 8
}
C++ supports robust error and exception handling using try, catch, and throw blocks, allowing programs to gracefully handle runtime errors.
try {
int a = 10, b = 0;
if(b == 0) throw runtime_error("Division by zero!");
cout << a / b << endl;
} catch (const exception &e) {
cout << "Error: " << e.what() << endl;
}
C++ is widely used across industries due to its speed, flexibility, and low-level capabilities. Some applications include:
System Software: Operating systems, file systems, and device drivers.
Game Development: Game engines like Unreal Engine rely on C++ for performance-intensive tasks.
Embedded Systems: Software for microcontrollers and hardware interfaces.
Finance: High-frequency trading platforms and banking applications.
Scientific Computing: Simulations, modeling, and data analysis tools.
Web Browsers: Parts of browsers like Chrome and Firefox are written in C++ for speed.
High performance due to direct hardware control.
Object-oriented design facilitates code organization.
Portability across platforms.
Wide community support and extensive libraries.
Supports multiple programming paradigms.
Manual memory management can lead to errors like memory leaks.
Complex syntax, especially for beginners.
Lack of built-in garbage collection.
Slower compile times compared to some modern languages.
Modern C++ standards have introduced features to simplify coding, improve safety, and enhance performance:
Auto keyword: Automatic type deduction.
Range-based for loops: Cleaner iteration over containers.
Smart pointers (unique_ptr, shared_ptr): Automatic memory management.
Lambda expressions: Inline anonymous functions.
Concurrency support: Multithreading features using thread and mutex.
Move semantics: Efficient transfer of resources without copying.
Example of a lambda function:
vector<int> nums = {1, 2, 3, 4};
int sum = 0;
for_each(nums.begin(), nums.end(), [&](int n){ sum += n; });
cout << "Sum: " << sum << endl; // Sum: 10
Answer:
C++ is a general-purpose, high-level programming language developed by Bjarne Stroustrup in 1983. It is an extension of the C language, adding Object-Oriented Programming (OOP) features like classes, inheritance, polymorphism, and encapsulation.
Key Features:
Supports both procedural and object-oriented programming.
Compiled language (fast execution).
Rich standard library (STL: Standard Template Library).
Supports low-level memory manipulation (pointers).
| Feature | C | C++ |
|---|---|---|
| Paradigm | Procedural | Procedural + Object-Oriented |
| Functions | Can’t be overloaded | Supports function overloading |
| Data Security | No data hiding | Supports encapsulation and data hiding |
| Inheritance | Not supported | Supported |
| Exception Handling | Not supported | Supported |
| Namespace | Not available | Available |
Answer:
Integer types: int, short, long, long long
Floating-point types: float, double, long double
Character type: char
Boolean type: bool (true or false)
Void type: void (used in functions that return nothing)
Arithmetic operators: +, -, *, /, %
Relational operators: ==, !=, >, <, >=, <=
Logical operators: &&, ||, !
Bitwise operators: &, |, ^, ~, <<, >>
Assignment operators: =, +=, -=, *=, /=, %=
Increment/Decrement: ++, --
Ternary operator: condition ? true_expr : false_expr
Class: A blueprint or template that defines data members (variables) and member functions (methods).
class Car {
public:
string brand;
void start() {
cout << "Car started" << endl;
}
};
Object: An instance of a class.
Car myCar; // myCar is an object of Car
myCar.brand = "Toyota";
myCar.start();
Answer:
Encapsulation is the concept of binding data and methods together in a class and restricting access to some components using access specifiers: private, protected, public.
Example:
class BankAccount {
private:
double balance;
public:
void deposit(double amt) {
balance += amt;
}
double getBalance() {
return balance;
}
};
Benefit: Data security and controlled access.
Answer:
Inheritance allows a class to acquire properties and behaviors of another class.
Base class (Parent): Class whose properties are inherited.
Derived class (Child): Class that inherits properties.
Example:
class Vehicle {
public:
void display() { cout << "This is a vehicle"; }
};
class Car : public Vehicle {
public:
void show() { cout << "This is a car"; }
};
Types of inheritance: Single, multiple, multilevel, hierarchical, hybrid.
Answer:
Polymorphism means "many forms". It allows the same function or operator to behave differently depending on context.
Compile-time (Static) polymorphism: Function overloading and operator overloading.
Run-time (Dynamic) polymorphism: Function overriding using virtual functions.
Example (Function Overloading):
class Math {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
};
Answer:
Abstraction hides implementation details and shows only functionality. Achieved using abstract classes with pure virtual functions.
Example:
class Shape {
public:
virtual void draw() = 0; // pure virtual function
};
Constructor: Special member function called automatically when an object is created.
class Car {
public:
Car() { cout << "Car object created"; } // Constructor
};
Destructor: Special member function called automatically when an object is destroyed.
~Car() { cout << "Car object destroyed"; } // Destructor
struct and class in C++?| Feature | struct | class |
|---|---|---|
| Default access specifier | public | private |
| Supports methods | Yes | Yes |
| Inheritance | Yes | Yes |
| Encapsulation | Weak | Strong |
new and malloc?| Feature | malloc | new |
|---|---|---|
| Library | C stdlib | C++ keyword |
| Constructor | Not called | Called automatically |
| Return type | void* |
Typed pointer |
| Free memory | free(ptr) |
delete ptr |
Pointer: Stores the address of a variable.
int a = 10;
int* ptr = &a;
Reference: An alias to an existing variable. Must be initialized when declared.
int a = 10;
int &ref = a;
++i and i++?++i → Pre-increment: Increments first, then returns the value.
i++ → Post-increment: Returns first, then increments the value.
Answer:
STL is a collection of classes and functions for commonly used data structures and algorithms.
Components:
Containers: vector, list, map, set, stack, queue
Algorithms: sort, reverse, find, count
Iterators: begin(), end(), rbegin(), rend()
Example:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {3,1,4,2};
sort(v.begin(), v.end());
for(int x : v) cout << x << " "; // Output: 1 2 3 4
}
virtual function and pure virtual function?| Feature | Virtual Function | Pure Virtual Function |
|---|---|---|
| Definition | Can have implementation | Must be overridden in derived class |
| Syntax | virtual void func(); |
virtual void func() = 0; |
| Object Creation | Class can be instantiated | Abstract class cannot be instantiated |
const keyword in C++?const variable: Value cannot be changed.
const function parameter: Function cannot modify the parameter.
const member function: Function cannot modify object data members.
class Car {
int speed;
public:
void show() const { cout << speed; } // Cannot modify speed
};
Stack memory: Stores local variables, automatically managed.
Heap memory: Dynamic memory allocated using new or malloc, must be manually deallocated.
Global/Static memory: Stores global and static variables, available throughout the program lifetime.
friend function in C++?Answer:
A friend function can access private and protected members of a class without being a member of that class.
class Box {
private:
int width;
public:
Box() { width = 10; }
friend void showWidth(Box b);
};
void showWidth(Box b) {
cout << b.width;
}
Answer:
Templates allow functions and classes to operate with generic types. Useful for code reusability.
Function template example:
template <typename T>
T add(T a, T b) {
return a + b;
}
Class template example:
template <class T>
class Box {
T value;
};
Answer:
Function overloading allows multiple functions with the same name but different parameter lists in the same scope. The compiler determines which function to call based on the arguments.
Example:
#include <iostream>
using namespace std;
class Math {
public:
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
};
int main() {
Math m;
cout << m.add(2,3) << endl; // Calls int version
cout << m.add(2.5,3.5) << endl; // Calls double version
}
Answer:
Operator overloading allows redefining the behavior of operators for user-defined types.
Example (Overloading + for a class):
#include <iostream>
using namespace std;
class Point {
int x, y;
public:
Point(int a, int b) : x(a), y(b) {}
Point operator + (const Point &p) {
return Point(x + p.x, y + p.y);
}
void display() { cout << x << "," << y << endl; }
};
int main() {
Point p1(2,3), p2(3,4);
Point p3 = p1 + p2;
p3.display(); // Output: 5,7
}
| Feature | Shallow Copy | Deep Copy |
|---|---|---|
| Definition | Copies only the pointer values | Copies the actual content the pointer points to |
| Risk | Changes in one object affect another | Objects are independent |
| Default in C++ | Copy constructor does shallow copy by default | Must implement manually |
Example of Deep Copy:
class Test {
int *p;
public:
Test(int val) { p = new int(val); }
Test(const Test &t) { p = new int(*t.p); } // Deep copy
~Test() { delete p; }
};
Answer:
A virtual destructor ensures that when a derived class object is deleted using a base class pointer, the derived class destructor is called to avoid memory leaks.
class Base {
public:
virtual ~Base() { cout << "Base destroyed\n"; }
};
class Derived : public Base {
public:
~Derived() { cout << "Derived destroyed\n"; }
};
int main() {
Base *b = new Derived();
delete b; // Calls Derived destructor first, then Base
}
throw(), try, and catch in C++?throw: Used to signal an exception.
try: Block of code where exceptions are monitored.
catch: Block that handles the exception.
Example:
try {
int a = 5, b = 0;
if(b == 0) throw "Division by zero";
cout << a/b;
} catch(const char* msg) {
cout << msg;
}
std::map and std::unordered_map?| Feature | map | unordered_map |
|---|---|---|
| Implementation | Balanced BST (Red-Black Tree) | Hash table |
| Time Complexity | O(log n) | O(1) average |
| Ordering | Sorted by key | Not sorted |
| Key Type | Comparable | Hashable |
Answer:
Smart pointers are RAII wrappers around raw pointers that manage memory automatically to prevent leaks.
Types in C++11+:
unique_ptr: Owns memory exclusively.
shared_ptr: Shared ownership; reference counted.
weak_ptr: Non-owning reference; breaks circular references.
Example:
#include <memory>
#include <iostream>
using namespace std;
int main() {
shared_ptr<int> p1 = make_shared<int>(10);
shared_ptr<int> p2 = p1; // Both share ownership
cout << *p1 << ", " << *p2; // Output: 10, 10
}
stack and heap memory| Feature | Stack | Heap |
|---|---|---|
| Allocation | Automatic | Manual (new/delete) |
| Size | Limited | Larger |
| Lifetime | Function scope | Until deleted |
| Access speed | Faster | Slower |
| Fragmentation | No | Possible |
const, constexpr, and #define?| Feature | const | constexpr | #define |
|---|---|---|---|
| Type Checking | Yes | Yes | No |
| Compile-Time Evaluation | No by default | Yes | Yes |
| Scope | Block/Function/Class | Block/Function/Class | Global |
| Example | const int a = 5; |
constexpr int b = 10; |
#define c 15 |
Answer:
A derived class can inherit from more than one base class. Be careful of the diamond problem, solved using virtual inheritance.
Example:
class A { public: void show() { cout << "A"; } };
class B { public: void show() { cout << "B"; } };
class C : public A, public B { };
int main() {
C obj;
obj.A::show(); // Resolves ambiguity
}
ofstream: Write to files.
ifstream: Read from files.
fstream: Read/write both.
Example:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ofstream file("data.txt");
file << "Hello C++";
file.close();
ifstream infile("data.txt");
string s;
infile >> s;
cout << s; // Output: Hello
infile.close();
}
malloc/free and new/delete| Feature | malloc/free | new/delete |
|---|---|---|
| Language | C | C++ |
| Constructor/Destructor | Not called | Called automatically |
| Return Type | void* | Typed pointer |
| Memory Error | Not checked | Throws bad_alloc on failure (if nothrow not used) |
Answer:
RAII is a C++ programming idiom where resources are acquired in a constructor and released in a destructor, ensuring proper cleanup.
Example: std::unique_ptr, file streams, mutex locks.
Answer:
Namespaces prevent name conflicts in large projects.
Example:
namespace First { int x = 10; }
namespace Second { int x = 20; }
int main() {
cout << First::x << " " << Second::x; // Output: 10 20
}
struct and class in terms of memory layoutBoth have the same memory layout for data members.
Only the default access specifier differs (struct: public, class: private).
Answer:
A lambda expression is an anonymous function defined directly in the code. Introduced in C++11, it’s useful for short operations, especially in algorithms.
Syntax:
[capture](parameters) -> return_type { body }
Example:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {1,2,3,4,5};
int sum = 0;
for_each(v.begin(), v.end(), [&sum](int x) { sum += x; });
cout << sum; // Output: 15
}
&sum captures the variable by reference.
Answer:
Move semantics (C++11) allows resources to be transferred from one object to another instead of copying, improving performance. Implemented using rvalue references (&&).
Example:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v1 = {1,2,3};
vector<int> v2 = std::move(v1); // v1 contents moved to v2
}
v1 becomes empty; no deep copy happens.
lvalue: Has a persistent memory location (can appear on the left of =).
int x = 5; // x is an lvalue
rvalue: Temporary object without a persistent location (usually on right of =).
int y = x + 2; // (x+2) is an rvalue
std::vector and std::array?| Feature | vector | array |
|---|---|---|
| Size | Dynamic | Fixed at compile-time |
| Memory | Heap | Stack (if local) |
| Resize | Yes | No |
| Performance | Slightly slower (dynamic allocation) | Faster (fixed size) |
std::list and std::vector?| Feature | vector | list |
|---|---|---|
| Data Structure | Dynamic array | Doubly linked list |
| Access | Random access O(1) | Sequential access O(n) |
| Insertion/Deletion | Expensive in middle O(n) | Fast O(1) |
| Memory Usage | Contiguous | Non-contiguous |
throw and noexcept?throw: Signals an exception.
noexcept: Tells compiler a function won’t throw exceptions, allowing optimization.
void f() noexcept { /* code */ }
std::unique_ptr, std::shared_ptr, and std::weak_ptr?Answer:
Smart pointers manage dynamic memory automatically:
unique_ptr: Exclusive ownership; cannot be copied.
shared_ptr: Multiple shared owners; uses reference counting.
weak_ptr: Non-owning reference; used to avoid cyclic references.
Shallow copy: Copies pointer address → two objects point to same memory → changes affect both.
Deep copy: Copies actual data → objects independent.
static, global, and local variables?| Feature | Static | Global | Local |
|---|---|---|---|
| Scope | Function/class | Whole program | Block/function |
| Lifetime | Entire program | Entire program | Function execution |
| Default value | 0 | 0 | Garbage (if not initialized) |
inline function and macro?inline function: Type-safe, evaluated at compile time if possible.
macro: Text substitution, no type checking.
Example of inline:
inline int add(int a, int b) { return a + b; }
Declared with =0.
Makes the class abstract; cannot create objects of it.
Forces derived classes to implement the function.
class Shape {
public:
virtual void draw() = 0; // Pure virtual
};
throw() specifier and modern C++ exception handling?Old C++: void f() throw(int); → restricts exceptions.
Modern C++: noexcept is preferred, as throw() is deprecated.
override and final keywords?override: Indicates a function overrides a base class virtual function.
final: Prevents a virtual function from being overridden in derived classes.
class Base { virtual void f() {} };
class Derived : public Base { void f() override final {} };
std::thread and multithreading in C++?C++11 introduced std::thread for multithreading.
Used to run multiple tasks concurrently.
Example:
#include <iostream>
#include <thread>
using namespace std;
void print() { cout << "Hello from thread\n"; }
int main() {
thread t(print);
t.join(); // Wait for thread to finish
}
call by value, call by reference, and call by pointer| Feature | Call by Value | Call by Reference | Call by Pointer |
|---|---|---|---|
| Passing | Copy of variable | Original variable | Address of variable |
| Changes affect caller | No | Yes | Yes |
| Syntax | f(x) | f(&x) or f(int &x) | f(&x) |
static and dynamic polymorphismStatic polymorphism: Compile-time (function/operator overloading, templates).
Dynamic polymorphism: Run-time (virtual functions, function overriding).
stack unwinding and exception propagationStack unwinding: When an exception occurs, destructors of stack objects are called in reverse order.
Exception propagation: Exception moves up the call stack until caught.
Objects that point to container elements.
Used for traversal, insertion, and deletion.
Types:
Input, Output, Forward, Bidirectional, Random Access
Example:
vector<int> v = {1,2,3};
for(auto it = v.begin(); it != v.end(); ++it)
cout << *it << " ";
std::vector::reserve and std::vector::resizereserve(n): Allocates memory for n elements but size remains same.
resize(n): Changes size of vector; initializes new elements if expanded.
delete and delete[]delete → deletes single object allocated by new.
delete[] → deletes array of objects allocated by new[].
int* p = new int;
delete p;
int* arr = new int[5];
delete[] arr;
| Feature | C++98 | C++11 | C++14 | C++17 | C++20 |
|---|---|---|---|---|---|
| Lambda expressions | No | Yes | Improved | Improved | Extended |
| auto keyword | No | Yes | Yes | Yes | Yes |
| smart pointers | No | Yes | Yes | Yes | Yes |
| constexpr | Limited | Yes | Relaxed | Improved | Enhanced |
| threading | No | std::thread | Yes | Yes | Yes |
| structured bindings | No | No | No | Yes | Yes |
| concepts & ranges | No | No | No | No | Yes |
Tip: Understand which modern features can replace older patterns, like auto, range-based for, move semantics, smart pointers.
Shallow copy: Copies pointer addresses; both objects point to the same memory → dangerous for dynamic memory.
Deep copy: Copies actual data to create independent objects.
Example:
class Test {
int *ptr;
public:
Test(int val) { ptr = new int(val); }
Test(const Test &t) { ptr = new int(*t.ptr); } // Deep copy
~Test() { delete ptr; }
};
Key point: Always implement copy constructor and assignment operator when class has dynamic memory.
virtual, pure virtual, and override?| Feature | virtual | pure virtual | override |
|---|---|---|---|
| Implementation | Can have body | No body (=0) | Overrides base class |
| Object Creation | Allowed | Not allowed | N/A |
| Purpose | Runtime polymorphism | Abstract class | Safe overriding |
Example:
class Base {
public:
virtual void show() { cout << "Base"; }
virtual void display() = 0; // Pure virtual
};
class Derived : public Base {
public:
void show() override { cout << "Derived"; }
void display() override { cout << "Display"; }
};
Rule of Three: If a class manages resources, implement destructor, copy constructor, and copy assignment operator.
Rule of Five (C++11): Also implement move constructor and move assignment operator for performance.
Rule of Zero: Prefer RAII containers and smart pointers so you don’t need to manage memory manually.
Example:
class Test {
int* data;
public:
Test(int val) { data = new int(val); }
~Test() { delete data; } // Destructor
Test(const Test &t) { data = new int(*t.data); } // Copy constructor
Test& operator=(const Test &t) { *data = *t.data; return *this; } // Assignment
};
Answer:
If a base class pointer points to a derived class object, a virtual destructor ensures proper cleanup of derived objects.
class Base { virtual ~Base() { cout << "Base destroyed\n"; } };
class Derived : public Base { ~Derived() { cout << "Derived destroyed\n"; } };
Base *b = new Derived();
delete b; // Calls Derived destructor first, then Base
Move semantics allow transferring resources instead of copying → improves performance.
Implemented using rvalue references (&&).
Example:
class Buffer {
int *data;
public:
Buffer(int size) { data = new int[size]; }
Buffer(Buffer &&b) noexcept : data(b.data) { b.data = nullptr; } // Move constructor
~Buffer() { delete[] data; }
};
Key point: Use std::move for efficient resource transfer.
std::unique_ptr, std::shared_ptr, and std::weak_ptr| Type | Ownership | Copyable | Use case |
|---|---|---|---|
| unique_ptr | Exclusive | No | Single ownership, fast |
| shared_ptr | Shared | Yes | Multiple owners, reference counted |
| weak_ptr | Observing | No | Avoid cyclic reference |
Example:
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = p1; // shared ownership
const, constexpr, volatile, and mutable?| Keyword | Meaning |
|---|---|
| const | Value cannot be modified |
| constexpr | Compile-time constant |
| volatile | Variable may change unexpectedly (used in hardware/multithreading) |
| mutable | Allows modifying member inside const function |
Raw pointer: Manual memory management → risky, can leak memory.
Smart pointer: Automatic memory management → safer, exception-safe.
Tip for interview: Always mention RAII principle when discussing smart pointers.
Types: Single, multiple, multilevel, hierarchical, hybrid.
Diamond problem: Resolved using virtual inheritance.
Example:
class A { public: int x; };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
Without virtual inheritance, D would have two copies of A.
std::thread and multithreading in C++11std::thread allows concurrent execution.
Use mutex, lock_guard, atomic to prevent data races.
Example:
#include <thread>
#include <iostream>
#include <mutex>
using namespace std;
mutex m;
void print(int x) {
lock_guard<mutex> lg(m);
cout << x << endl;
}
int main() {
thread t1(print,1), t2(print,2);
t1.join(); t2.join();
}
std::vector vs std::list vs std::deque| Container | Access | Insert/Delete | Memory |
|---|---|---|---|
| vector | Random O(1) | Middle O(n) | Contiguous |
| list | Sequential O(n) | O(1) anywhere | Non-contiguous |
| deque | Random O(1) | Front/back O(1) | Non-contiguous chunks |
Stack: Local variables, automatically managed.
Heap: Dynamically allocated, manually managed using new/delete or smart pointers.
Global/Static: Lifetime of program, initialized once.
Tips: Always free heap memory; avoid memory leaks.
Use try/catch blocks.
Always catch by reference (const T&).
Avoid exceptions in destructors.
Prefer RAII to manage resources instead of manual cleanup.
STL components and iteratorsContainers: vector, list, map, set, stack, queue
Algorithms: sort, find, count, accumulate
Iterators: Input, Output, Forward, Bidirectional, Random-access
Example with vector:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
vector<int> v = {3,1,4,2};
sort(v.begin(), v.end());
for(int x : v) cout << x << " ";
Function templates: Generic functions
Class templates: Generic classes
STL containers are template classes
Example:
template <typename T>
T add(T a, T b) { return a + b; }
mutable keyword and const member functionsmutable: Allows modification of data member inside const function.
const function: Cannot modify object data members.
class Test {
mutable int counter;
public:
void show() const { counter++; }
};
RAII and resource managementRAII = Resource Acquisition Is Initialization.
Acquire resources (memory, file handles, mutex) in constructor and release in destructor.
Ensures exception safety.
std::move vs std::forwardstd::move: Converts lvalue to rvalue to enable move semantics.
std::forward: Perfect forwarding in templates; preserves value category.
C++11: auto, nullptr, smart pointers, move semantics, lambdas
C++14: generic lambdas, relaxed constexpr
C++17: structured bindings, if constexpr, optional
C++20: concepts, ranges, coroutines, modules
std::map and std::unordered_map| Feature | std::map | std::unordered_map |
|---|---|---|
| Implementation | Red-Black Tree | Hash Table |
| Key Ordering | Sorted | Not sorted |
| Lookup Complexity | O(log n) | O(1) average |
| Memory | Less | More (hash table overhead) |
Example:
#include <map>
#include <unordered_map>
#include <iostream>
using namespace std;
map<int, string> m1;
unordered_map<int, string> m2;
std::set vs std::unordered_setset: Stores unique elements in sorted order (RB-tree).
unordered_set: Stores unique elements unordered (hash table).
Lookup: set O(log n), unordered_set O(1) average.
Answer:
Design patterns provide reusable solutions to common problems.
Creational: Singleton, Factory, Builder
Structural: Adapter, Composite, Decorator
Behavioral: Observer, Strategy, Command
Example (Singleton):
class Singleton {
static Singleton* instance;
Singleton() {}
public:
static Singleton* getInstance() {
if(!instance) instance = new Singleton();
return instance;
}
};
Singleton* Singleton::instance = nullptr;
Thread: Independent execution path.
Mutex: Protects shared data from race conditions.
Lock_guard: RAII wrapper for mutex.
Atomic: Lock-free thread-safe variables.
Example:
#include <thread>
#include <mutex>
#include <iostream>
using namespace std;
mutex m;
int counter = 0;
void increment() {
lock_guard<mutex> lg(m);
counter++;
}
int main() {
thread t1(increment), t2(increment);
t1.join(); t2.join();
cout << counter;
}
Prefer RAII and smart pointers (unique_ptr, shared_ptr).
Avoid manual new/delete whenever possible.
Use stack memory for local variables for speed.
Avoid memory leaks by properly deleting dynamically allocated memory.
| Feature | Copy Constructor | Move Constructor |
|---|---|---|
| Purpose | Copy data from one object to another | Transfer resources without copying |
| Performance | Slower for dynamic memory | Faster, no deep copy |
| Syntax | Class(const Class &obj) |
Class(Class &&obj) |
ifstream: Read from files
ofstream: Write to files
fstream: Read/Write
Example:
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ofstream out("file.txt");
out << "Hello C++";
out.close();
ifstream in("file.txt");
string s;
in >> s;
cout << s; // Output: Hello
}
No-throw guarantee: Function never throws.
Strong guarantee: State unchanged if exception occurs.
Basic guarantee: Program remains valid; object may be modified.
Tip: Use RAII for exception-safe resource management.
std::thread vs std::async| Feature | std::thread | std::async |
|---|---|---|
| Type | Explicit thread creation | Asynchronous task |
| Return value | void or manually handled | Future/return value handled |
| Synchronization | join() | get() waits for result |
| Usage | Low-level threading | High-level task management |
constexpr vs constconst: Value cannot change; may be runtime constant.
constexpr: Must be compile-time constant; can be used in array sizes, templates.
constexpr int size = 10;
int arr[size];
shared_ptr cycles → memory leak (use weak_ptr).
unique_ptr cannot be copied.
Mixing raw and smart pointers → undefined behavior.
std::function, std::bind, and callbacksstd::function: Stores callable objects (functions, lambdas, functors).
std::bind: Creates a callable by binding arguments.
Example:
#include <functional>
#include <iostream>
using namespace std;
void print(int x) { cout << x; }
int main() {
function<void(int)> f = print;
f(10); // Output: 10
}
[=] vs [&] vs [this][=]: Capture by value (copy)
[&]: Capture by reference
[this]: Capture class members
Example:
int x = 5;
auto lambda = [=]() { cout << x; }; // captures x by value
std::move vs std::forwardstd::move: Converts lvalue to rvalue → enables move constructor/assignment.
std::forward: Perfect forwarding in templates; preserves lvalue/rvalue nature.
Multiple inheritance may create duplicate base class objects.
Virtual inheritance ensures only one base class instance.
class A { };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
sort: O(n log n)
find: O(n) for vector/list, O(log n) for map/set
accumulate: O(n)
lower_bound/upper_bound: O(log n) in sorted containers
Resource allocation in constructor, deallocation in destructor.
Ensures no leaks, even with exceptions.
Example: std::unique_ptr, std::lock_guard.
Inline function: Type safe, evaluated at compile-time if small.
Macro: Text substitution, no type checking.
Prefer inline in modern C++.
override vs final keywordsoverride: Ensures function overrides a base virtual function.
final: Prevents derived classes from overriding the function.
Prefer move semantics to copying.
Use reserve() for vectors to reduce reallocations.
Avoid unnecessary dynamic allocation.
Use emplace_back() instead of push_back().
Minimize virtual function calls in tight loops.
std::vector, std::list, std::deque and when to use them| Container | Access | Insertion/Deletion | Memory | Use case |
|---|---|---|---|---|
| vector | Random O(1) | Middle O(n), Back O(1) amortized | Contiguous | Dynamic array, frequent random access |
| list | Sequential O(n) | O(1) anywhere | Non-contiguous | Frequent insert/delete in middle |
| deque | Random O(1) | Front/Back O(1) | Non-contiguous chunks | Double-ended queue, random access |
std::shared_ptr and std::weak_ptrshared_ptr: Reference-counted smart pointer; owns memory.
weak_ptr: Non-owning pointer to avoid cyclic references.
Common pattern: shared_ptr + weak_ptr in graphs or trees.
Example:
#include <memory>
#include <iostream>
using namespace std;
struct Node {
shared_ptr<Node> next;
weak_ptr<Node> prev; // avoids cycle
};
Copy elision: Compiler optimization to avoid unnecessary copies.
RVO (Return Value Optimization): Eliminates temporary objects in return statements.
MyClass func() {
MyClass obj;
return obj; // May avoid copy via RVO
}
In C++17, mandatory copy elision is applied in some cases.
const_cast, static_cast, dynamic_cast, reinterpret_cast| Cast | Use case | Safety |
|---|---|---|
| const_cast | Remove/add constness | Safe for constness only |
| static_cast | Compile-time conversions | Checked at compile-time |
| dynamic_cast | Safe downcasting (polymorphism) | Requires virtual base, returns nullptr if invalid |
| reinterpret_cast | Low-level pointer conversions | Unsafe, platform-dependent |
Type erasure abstracts different types with the same interface into a single type.
Common in std::function and polymorphic wrappers.
Allows generic programming without templates everywhere.
Example:
std::function<int(int)> f = [](int x){ return x + 1; };
Race condition: Multiple threads access shared data unsafely.
Deadlock: Two or more threads wait indefinitely for resources.
Livelock: Threads actively change state but cannot progress.
Prevention techniques:
Use mutexes, lock ordering, lock_guard, std::unique_lock.
Avoid nested locks when possible.
std::atomicstd::atomic provides thread-safe operations without mutexes.
Useful for high-performance concurrent programming.
Example:
#include <atomic>
#include <thread>
#include <iostream>
using namespace std;
atomic<int> counter(0);
void increment() { counter++; }
int main() {
thread t1(increment), t2(increment);
t1.join(); t2.join();
cout << counter; // Always 2
}
Alignment: Objects stored at addresses multiples of their size or compiler-defined alignment.
Padding: Compiler adds extra bytes to satisfy alignment.
Impact: Improves CPU access speed; may waste memory.
struct S {
char a; // 1 byte
int b; // 4 bytes
}; // sizeof(S) may be 8 due to padding
vtable: Table storing addresses of virtual functions for a class.
vptr: Pointer inside object pointing to vtable.
Purpose: Supports runtime polymorphism.
Tip: Each object with virtual functions contains a hidden vptr.
Multiple inheritance may create duplicate base class objects.
Solution: Virtual inheritance.
class A { };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
Only one A is present in D.
std::function vs function pointersstd::function: Can hold function, lambda, functor.
Function pointers: Only hold regular functions.
std::function adds type erasure and flexibility.
std::function<int(int,int)> f = [](int a, int b){ return a+b; };
If constructor throws → object not created; destructor not called.
Use RAII to ensure resource cleanup.
Avoid throwing exceptions in destructors.
Allows different implementation for specific types.
template<typename T>
class MyClass { void display(){ cout << "Generic"; } };
template<>
class MyClass<int> { void display(){ cout << "Int specialization"; } };
constexpr and consteval in C++20constexpr: Evaluated at compile-time if possible.
consteval: Must be evaluated at compile-time.
consteval int square(int x) { return x*x; }
int a = square(5); // compile-time
Cyclic reference: shared_ptr pointing to each other → memory leak.
Solution: Use weak_ptr for back-references.
struct Node {
shared_ptr<Node> next;
weak_ptr<Node> prev; // avoids cycle
};
sort: O(n log n), works with random-access iterators.
stable_sort: Maintains relative order of equal elements.
lower_bound / upper_bound: Binary search on sorted containers.
accumulate: Sum elements.
vector<int> v = {1,2,3};
int sum = accumulate(v.begin(), v.end(), 0);
Move semantics: Transfers resources instead of copying.
Perfect forwarding: Pass arguments preserving value category.
template<typename T>
void func(T&& arg) {
process(std::forward<T>(arg));
}
Singleton: Only one instance.
Factory: Object creation without exposing class names.
Observer: Event subscription and notification.
Strategy: Swap algorithms at runtime.
C++14/17 allows moving objects into lambda.
std::unique_ptr<int> p = std::make_unique<int>(10);
auto lambda = [ptr = std::move(p)](){ cout << *ptr; };
Prefer stack allocation for temporary objects.
Use reserve() for vectors to reduce reallocations.
Use emplace_back() to construct in-place.
Avoid virtual calls in tight loops if possible.