C++ Programming Mastery Guide
Complete guide from OOP basics to modern C++ features
The Complete C++ Programming Mastery Guide
Master object-oriented programming, templates, STL, and modern C++ features for high-performance applications
Understanding C++: Power and Performance
C++ is a powerful, high-performance programming language created by Bjarne Stroustrup as an extension of C. It combines low-level memory manipulation with high-level object-oriented features, making it ideal for system software, game development, high-frequency trading, and performance-critical applications.
What makes C++ unique is its "zero-cost abstractions" philosophy - you don't pay for features you don't use. Modern C++ (C++11 and beyond) introduces powerful features like smart pointers, lambda expressions, and move semantics while maintaining backward compatibility.
Industry Powerhouse: C++ powers major software like Google Chrome, Microsoft Windows, Adobe Creative Suite, Unreal Engine, and MySQL. Its performance makes it the language of choice for applications where speed and efficiency are critical.
1. C++ Basics & OOP Fundamentals
Hello World: Your First C++ Program
// hello.cpp
#include <iostream> // Input/output stream
#include <string> // String class
using namespace std; // Use standard namespace
int main() {
cout << "Hello, World!" << endl;
cout << "Welcome to C++ Programming!" << endl;
// String manipulation
string name = "Alice";
cout << "Hello, " << name << "!" << endl;
// Input from user
int age;
cout << "Enter your age: ";
cin >> age;
cout << "You are " << age << " years old." << endl;
return 0;
}
// Compile and run:
// g++ hello.cpp -o hello
// ./helloC++ Enhancements Over C
#include <iostream>
using namespace std;
// Function overloading - same name, different parameters
void print(int value) {
cout << "Integer: " << value << endl;
}
void print(double value) {
cout << "Double: " << value << endl;
}
void print(const string& value) {
cout << "String: " << value << endl;
}
// Default parameters
void greet(string name, string greeting = "Hello") {
cout << greeting << ", " << name << "!" << endl;
}
// References (safer alternative to pointers)
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
int main() {
// C++ specific types
bool isCppFun = true;
cout << "Is C++ fun? " << boolalpha << isCppFun << endl;
// Function overloading demonstration
print(42);
print(3.14159);
print("Hello C++");
// Default parameters
greet("Alice");
greet("Bob", "Good morning");
// References
int x = 10, y = 20;
cout << "Before swap: x=" << x << ", y=" << y << endl;
swap(x, y);
cout << "After swap: x=" << x << ", y=" << y << endl;
// Reference variables
int original = 100;
int& ref = original; // ref is an alias for original
ref = 200;
cout << "original: " << original << ", ref: " << ref << endl;
return 0;
}Namespaces and Scope Resolution
#include <iostream>
#include <string>
// Custom namespace
namespace MathOperations {
const double PI = 3.14159;
double add(double a, double b) {
return a + b;
}
double multiply(double a, double b) {
return a * b;
}
// Nested namespace
namespace Geometry {
double circleArea(double radius) {
return PI * radius * radius;
}
}
}
// Global variable
int globalVar = 100;
// Another namespace
namespace StringUtils {
void printLength(const std::string& str) {
std::cout << "Length: " << str.length() << std::endl;
}
}
int main() {
// Using namespace members
std::cout << "PI: " << MathOperations::PI << std::endl;
std::cout << "5 + 3 = " << MathOperations::add(5, 3) << std::endl;
std::cout << "Circle area: " << MathOperations::Geometry::circleArea(5.0) << std::endl;
// Using directive
using StringUtils::printLength;
printLength("Hello C++");
// Scope resolution for global variables
int globalVar = 50; // Local variable shadows global
std::cout << "Local globalVar: " << globalVar << std::endl;
std::cout << "Global globalVar: " << ::globalVar << std::endl;
// Creating alias for long namespace
namespace MO = MathOperations;
std::cout << "Using alias: " << MO::multiply(4, 5) << std::endl;
return 0;
}Memory Management: new and delete
#include <iostream>
using namespace std;
class Point {
public:
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {
cout << "Point constructed: (" << x << ", " << y << ")" << endl;
}
~Point() {
cout << "Point destroyed: (" << x << ", " << y << ")" << endl;
}
};
int main() {
// Single object allocation
Point* p1 = new Point(10, 20);
cout << "p1: (" << p1->x << ", " << p1->y << ")" << endl;
// Array allocation
int size = 5;
int* arr = new int[size];
for (int i = 0; i < size; i++) {
arr[i] = (i + 1) * 10;
}
cout << "Array elements: ";
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
// Array of objects
Point* points = new Point[3] {
Point(1, 1),
Point(2, 2),
Point(3, 3)
};
// Memory deallocation
delete p1; // Single object
delete[] arr; // Array of primitives
delete[] points; // Array of objects
// Memory allocation with initialization
int* value = new int(42); // Initialize with 42
cout << "Initialized value: " << *value << endl;
delete value;
// Checking for allocation failure (modern approach uses exceptions)
try {
int* hugeArray = new int[1000000000000LL]; // Very large allocation
delete[] hugeArray;
} catch (const bad_alloc& e) {
cout << "Memory allocation failed: " << e.what() << endl;
}
return 0;
}2. Classes & Object-Oriented Programming
Class Basics: Encapsulation and Abstraction
#include <iostream>
#include <string>
using namespace std;
class BankAccount {
private:
string accountNumber;
string accountHolder;
double balance;
// Private helper method
bool isValidAmount(double amount) const {
return amount > 0;
}
public:
// Constructor
BankAccount(const string& number, const string& holder, double initialBalance = 0.0)
: accountNumber(number), accountHolder(holder), balance(initialBalance) {
cout << "Account created for " << holder << endl;
}
// Destructor
~BankAccount() {
cout << "Account " << accountNumber << " is being closed" << endl;
}
// Public interface
void deposit(double amount) {
if (isValidAmount(amount)) {
balance += amount;
cout << "Deposited: $" << amount << endl;
} else {
cout << "Invalid deposit amount!" << endl;
}
}
bool withdraw(double amount) {
if (isValidAmount(amount) && amount <= balance) {
balance -= amount;
cout << "Withdrawn: $" << amount << endl;
return true;
}
cout << "Withdrawal failed!" << endl;
return false;
}
// Const member function - doesn't modify object state
double getBalance() const {
return balance;
}
void displayInfo() const {
cout << "Account: " << accountNumber << endl;
cout << "Holder: " << accountHolder << endl;
cout << "Balance: $" << balance << endl;
}
// Static member
static string getBankName() {
return "C++ Bank";
}
};
int main() {
// Creating objects
BankAccount account1("123456", "Alice", 1000.0);
BankAccount account2("789012", "Bob");
// Using object methods
account1.displayInfo();
account1.deposit(500.0);
account1.withdraw(200.0);
account1.withdraw(2000.0); // Should fail
cout << "Current balance: $" << account1.getBalance() << endl;
// Static member access
cout << "Bank name: " << BankAccount::getBankName() << endl;
return 0;
// Destructors called automatically when objects go out of scope
}Inheritance and Polymorphism
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Base class
class Shape {
protected:
string name;
string color;
public:
Shape(const string& n, const string& c) : name(n), color(c) {}
// Virtual function for polymorphism
virtual double area() const = 0; // Pure virtual function
virtual void display() const {
cout << "Shape: " << name << ", Color: " << color;
}
// Virtual destructor for proper cleanup
virtual ~Shape() {
cout << "Shape " << name << " destroyed" << endl;
}
};
// Derived class
class Circle : public Shape {
private:
double radius;
public:
Circle(const string& n, const string& c, double r)
: Shape(n, c), radius(r) {}
// Override base class function
double area() const override {
return 3.14159 * radius * radius;
}
void display() const override {
Shape::display();
cout << ", Radius: " << radius << ", Area: " << area() << endl;
}
};
class Rectangle : public Shape {
private:
double width, height;
public:
Rectangle(const string& n, const string& c, double w, double h)
: Shape(n, c), width(w), height(h) {}
double area() const override {
return width * height;
}
void display() const override {
Shape::display();
cout << ", Width: " << width << ", Height: " << height
<< ", Area: " << area() << endl;
}
};
int main() {
// Polymorphism in action
vector<Shape*> shapes;
shapes.push_back(new Circle("Circle1", "Red", 5.0));
shapes.push_back(new Rectangle("Rect1", "Blue", 4.0, 6.0));
shapes.push_back(new Circle("Circle2", "Green", 3.0));
cout << "Polymorphic behavior:" << endl;
for (Shape* shape : shapes) {
shape->display(); // Calls appropriate derived class function
}
// Cleanup
for (Shape* shape : shapes) {
delete shape;
}
// Object slicing demonstration
Circle circle("MyCircle", "Yellow", 10.0);
Shape shape = circle; // Object slicing - Circle part is lost
shape.display();
cout << endl;
return 0;
}Operator Overloading
#include <iostream>
#include <cmath>
using namespace std;
class Vector3D {
private:
double x, y, z;
public:
// Constructors
Vector3D(double x = 0, double y = 0, double z = 0) : x(x), y(y), z(z) {}
// Operator overloading
Vector3D operator+(const Vector3D& other) const {
return Vector3D(x + other.x, y + other.y, z + other.z);
}
Vector3D operator-(const Vector3D& other) const {
return Vector3D(x - other.x, y - other.y, z - other.z);
}
// Dot product
double operator*(const Vector3D& other) const {
return x * other.x + y * other.y + z * other.z;
}
// Scalar multiplication
Vector3D operator*(double scalar) const {
return Vector3D(x * scalar, y * scalar, z * scalar);
}
// Friend function for commutative scalar multiplication
friend Vector3D operator*(double scalar, const Vector3D& vec);
// Compound assignment
Vector3D& operator+=(const Vector3D& other) {
x += other.x;
y += other.y;
z += other.z;
return *this;
}
// Comparison operators
bool operator==(const Vector3D& other) const {
return x == other.x && y == other.y && z == other.z;
}
bool operator!=(const Vector3D& other) const {
return !(*this == other);
}
// Subscript operator
double operator[](int index) const {
switch(index) {
case 0: return x;
case 1: return y;
case 2: return z;
default: throw out_of_range("Index out of range");
}
}
// Output stream operator
friend ostream& operator<<(ostream& os, const Vector3D& vec);
// Magnitude
double magnitude() const {
return sqrt(x*x + y*y + z*z);
}
// Normalize
Vector3D normalize() const {
double mag = magnitude();
if (mag == 0) return *this;
return *this * (1.0 / mag);
}
};
// Friend function definitions
Vector3D operator*(double scalar, const Vector3D& vec) {
return vec * scalar; // Reuse member function
}
ostream& operator<<(ostream& os, const Vector3D& vec) {
os << "(" << vec.x << ", " << vec.y << ", " << vec.z << ")";
return os;
}
int main() {
Vector3D v1(1, 2, 3);
Vector3D v2(4, 5, 6);
cout << "v1 = " << v1 << endl;
cout << "v2 = " << v2 << endl;
Vector3D v3 = v1 + v2;
cout << "v1 + v2 = " << v3 << endl;
Vector3D v4 = v1 - v2;
cout << "v1 - v2 = " << v4 << endl;
double dot = v1 * v2;
cout << "v1 · v2 = " << dot << endl;
Vector3D v5 = v1 * 2.5;
cout << "v1 * 2.5 = " << v5 << endl;
Vector3D v6 = 3.0 * v1;
cout << "3.0 * v1 = " << v6 << endl;
v1 += v2;
cout << "v1 after += v2: " << v1 << endl;
cout << "v1 magnitude: " << v1.magnitude() << endl;
cout << "v1 normalized: " << v1.normalize() << endl;
cout << "v1[0] = " << v1[0] << ", v1[1] = " << v1[1] << ", v1[2] = " << v1[2] << endl;
return 0;
}Friend Functions and Static Members
#include <iostream>
#include <vector>
using namespace std;
class Student {
private:
string name;
int id;
double gpa;
// Static member - shared by all Student objects
static int totalStudents;
static int nextId;
public:
Student(const string& n, double g) : name(n), gpa(g), id(nextId++) {
totalStudents++;
}
~Student() {
totalStudents--;
}
// Friend function declaration
friend void displayStudentInfo(const Student& s);
// Friend class
friend class StudentManager;
// Static member functions
static int getTotalStudents() {
return totalStudents;
}
static void resetIds() {
nextId = 1000; // Start IDs from 1000
}
// Regular member functions
string getName() const { return name; }
double getGpa() const { return gpa; }
int getId() const { return id; }
};
// Static member definitions
int Student::totalStudents = 0;
int Student::nextId = 1000;
// Friend function definition
void displayStudentInfo(const Student& s) {
cout << "Student ID: " << s.id << endl; // Can access private members
cout << "Name: " << s.name << endl;
cout << "GPA: " << s.gpa << endl;
}
// Friend class
class StudentManager {
private:
vector<Student*> students;
public:
void addStudent(Student* student) {
students.push_back(student);
}
void displayAllStudents() {
cout << "=== All Students ===" << endl;
for (Student* s : students) {
// Can access private members because friend
cout << s->id << ": " << s->name << " (GPA: " << s->gpa << ")" << endl;
}
}
double getAverageGPA() const {
if (students.empty()) return 0.0;
double total = 0.0;
for (Student* s : students) {
total += s->gpa; // Access private member
}
return total / students.size();
}
};
int main() {
// Demonstrate static members
cout << "Initial total students: " << Student::getTotalStudents() << endl;
Student s1("Alice", 3.8);
Student s2("Bob", 3.2);
Student s3("Charlie", 3.9);
cout << "After creating 3 students: " << Student::getTotalStudents() << endl;
// Using friend function
cout << "\nUsing friend function:" << endl;
displayStudentInfo(s1);
// Using friend class
StudentManager manager;
manager.addStudent(&s1);
manager.addStudent(&s2);
manager.addStudent(&s3);
manager.displayAllStudents();
cout << "Average GPA: " << manager.getAverageGPA() << endl;
// Demonstrate object destruction
{
Student temp("Temporary", 2.5);
cout << "Total students in block: " << Student::getTotalStudents() << endl;
} // temp destroyed here
cout << "After block: " << Student::getTotalStudents() << endl;
return 0;
}3. Templates & Generic Programming
Function Templates
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Basic function template
template<typename T>
T max(const T& a, const T& b) {
return (a > b) ? a : b;
}
// Template with multiple types
template<typename T1, typename T2>
void printPair(const T1& first, const T2& second) {
cout << "(" << first << ", " << second << ")" << endl;
}
// Template specialization
template<>
const char* max(const char* const & a, const char* const & b) {
return (strcmp(a, b) > 0) ? a : b;
}
// Template with non-type parameters
template<typename T, int size>
class FixedArray {
private:
T data[size];
public:
T& operator[](int index) {
if (index < 0 || index >= size) {
throw out_of_range("Index out of bounds");
}
return data[index];
}
const T& operator[](int index) const {
if (index < 0 || index >= size) {
throw out_of_range("Index out of bounds");
}
return data[index];
}
int getSize() const { return size; }
};
// Variadic templates (C++11)
template<typename T>
void print(const T& value) {
cout << value << endl;
}
template<typename T, typename... Args>
void print(const T& first, const Args&... rest) {
cout << first << " ";
print(rest...);
}
int main() {
// Using function templates
cout << "max(5, 10) = " << max(5, 10) << endl;
cout << "max(3.14, 2.71) = " << max(3.14, 2.71) << endl;
cout << "max('a', 'z') = " << max('a', 'z') << endl;
string s1 = "hello", s2 = "world";
cout << "max(strings) = " << max(s1, s2) << endl;
// Using specialized version for C-strings
cout << "max(C-strings) = " << max("apple", "banana") << endl;
// Multiple type parameters
printPair(42, "answer");
printPair(3.14, "pi");
// Non-type template parameters
FixedArray<int, 5> intArray;
for (int i = 0; i < intArray.getSize(); i++) {
intArray[i] = (i + 1) * 10;
}
cout << "Fixed array: ";
for (int i = 0; i < intArray.getSize(); i++) {
cout << intArray[i] << " ";
}
cout << endl;
// Variadic templates
print(1, 2, 3, "hello", 4.5, 'X');
return 0;
}Class Templates
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;
// Basic class template
template<typename T>
class Stack {
private:
vector<T> elements;
public:
// Push element onto stack
void push(const T& value) {
elements.push_back(value);
}
// Pop element from stack
void pop() {
if (elements.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
elements.pop_back();
}
// Get top element
T top() const {
if (elements.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
return elements.back();
}
// Check if stack is empty
bool empty() const {
return elements.empty();
}
// Get size
size_t size() const {
return elements.size();
}
};
// Template with default parameters
template<typename T = int, int initialCapacity = 10>
class DynamicArray {
private:
T* data;
int capacity;
int count;
public:
DynamicArray() : capacity(initialCapacity), count(0) {
data = new T[capacity];
}
~DynamicArray() {
delete[] data;
}
void add(const T& value) {
if (count >= capacity) {
// Resize
capacity *= 2;
T* newData = new T[capacity];
for (int i = 0; i < count; i++) {
newData[i] = data[i];
}
delete[] data;
data = newData;
}
data[count++] = value;
}
T& operator[](int index) {
if (index < 0 || index >= count) {
throw out_of_range("Index out of bounds");
}
return data[index];
}
int size() const { return count; }
int getCapacity() const { return capacity; }
};
// Template inheritance
template<typename T>
class LoggingStack : public Stack<T> {
public:
void push(const T& value) {
cout << "Pushing: " << value << endl;
Stack<T>::push(value);
}
void pop() {
if (!this->empty()) {
cout << "Popping: " << this->top() << endl;
Stack<T>::pop();
}
}
};
int main() {
// Using class template
Stack<int> intStack;
intStack.push(10);
intStack.push(20);
intStack.push(30);
cout << "Stack size: " << intStack.size() << endl;
cout << "Top element: " << intStack.top() << endl;
intStack.pop();
cout << "After pop, top: " << intStack.top() << endl;
// Stack with strings
Stack<string> stringStack;
stringStack.push("hello");
stringStack.push("world");
cout << "String stack top: " << stringStack.top() << endl;
// Using template with default parameters
DynamicArray<> defaultArray; // Uses default types (int, capacity 10)
DynamicArray<double, 5> doubleArray;
for (int i = 0; i < 15; i++) {
defaultArray.add(i * 10);
}
cout << "Default array size: " << defaultArray.size()
<< ", capacity: " << defaultArray.getCapacity() << endl;
// Using derived template class
LoggingStack<int> loggingStack;
loggingStack.push(100);
loggingStack.push(200);
loggingStack.pop();
return 0;
}4. STL Containers & Algorithms
STL Containers: Vector, List, Map
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <unordered_map>
#include <set>
#include <algorithm>
#include <string>
using namespace std;
void demonstrateVector() {
cout << "=== VECTOR ===" << endl;
vector<int> vec = {1, 2, 3, 4, 5};
// Adding elements
vec.push_back(6);
vec.insert(vec.begin() + 2, 99);
// Accessing elements
cout << "Element at index 2: " << vec[2] << endl;
cout << "Front: " << vec.front() << ", Back: " << vec.back() << endl;
// Iterating
cout << "Elements: ";
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// Range-based for loop (C++11)
cout << "Range-based: ";
for (int value : vec) {
cout << value << " ";
}
cout << endl;
// Capacity
cout << "Size: " << vec.size() << ", Capacity: " << vec.capacity() << endl;
}
void demonstrateList() {
cout << "\n=== LIST ===" << endl;
list<string> names = {"Alice", "Bob", "Charlie"};
names.push_front("First");
names.push_back("Last");
// List-specific operations
names.sort();
names.unique();
cout << "Names: ";
for (const auto& name : names) {
cout << name << " ";
}
cout << endl;
}
void demonstrateMap() {
cout << "\n=== MAP ===" << endl;
map<string, int> ageMap = {
{"Alice", 25},
{"Bob", 30},
{"Charlie", 35}
};
// Inserting
ageMap["Diana"] = 28;
ageMap.insert({"Eve", 32});
// Accessing
cout << "Alice's age: " << ageMap["Alice"] << endl;
// Iterating through map
cout << "All ages:" << endl;
for (const auto& pair : ageMap) {
cout << pair.first << ": " << pair.second << endl;
}
// Finding elements
auto it = ageMap.find("Bob");
if (it != ageMap.end()) {
cout << "Found Bob: " << it->second << endl;
}
}
void demonstrateAlgorithms() {
cout << "\n=== ALGORITHMS ===" << endl;
vector<int> numbers = {5, 2, 8, 1, 9, 3, 7, 4, 6};
// Sorting
sort(numbers.begin(), numbers.end());
cout << "Sorted: ";
for (int n : numbers) cout << n << " ";
cout << endl;
// Finding
auto found = find(numbers.begin(), numbers.end(), 7);
if (found != numbers.end()) {
cout << "Found 7 at position: " << distance(numbers.begin(), found) << endl;
}
// Counting
int countFives = count(numbers.begin(), numbers.end(), 5);
cout << "Number of 5s: " << countFives << endl;
// Lambda expressions with algorithms (C++11)
cout << "Even numbers: ";
for_each(numbers.begin(), numbers.end(), [](int n) {
if (n % 2 == 0) cout << n << " ";
});
cout << endl;
// Transform
vector<int> squared;
transform(numbers.begin(), numbers.end(), back_inserter(squared),
[](int n) { return n * n; });
cout << "Squared: ";
for (int n : squared) cout << n << " ";
cout << endl;
}
int main() {
demonstrateVector();
demonstrateList();
demonstrateMap();
demonstrateAlgorithms();
return 0;
}Smart Pointers (C++11 and beyond)
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class Resource {
private:
string name;
public:
Resource(const string& n) : name(n) {
cout << "Resource " << name << " created" << endl;
}
~Resource() {
cout << "Resource " << name << " destroyed" << endl;
}
void use() {
cout << "Using resource " << name << endl;
}
string getName() const { return name; }
};
void demonstrateUniquePtr() {
cout << "=== UNIQUE_PTR ===" << endl;
// Creating unique_ptr
unique_ptr<Resource> res1 = make_unique<Resource>("Unique1");
res1->use();
// Transfer ownership (move semantics)
unique_ptr<Resource> res2 = move(res1);
if (!res1) {
cout << "res1 is now empty" << endl;
}
res2->use();
// unique_ptr in containers
vector<unique_ptr<Resource>> resources;
resources.push_back(make_unique<Resource>("Vector1"));
resources.push_back(make_unique<Resource>("Vector2"));
for (const auto& res : resources) {
res->use();
}
} // Resources automatically destroyed here
void demonstrateSharedPtr() {
cout << "\n=== SHARED_PTR ===" << endl;
// Creating shared_ptr
shared_ptr<Resource> res1 = make_shared<Resource>("Shared1");
cout << "Use count: " << res1.use_count() << endl;
{
shared_ptr<Resource> res2 = res1; // Share ownership
cout << "Use count after sharing: " << res1.use_count() << endl;
res2->use();
} // res2 destroyed, but resource remains
cout << "Use count after res2 destruction: " << res1.use_count() << endl;
res1->use();
}
void demonstrateWeakPtr() {
cout << "\n=== WEAK_PTR ===" << endl;
shared_ptr<Resource> shared = make_shared<Resource>("WeakDemo");
weak_ptr<Resource> weak = shared;
cout << "Shared use count: " << shared.use_count() << endl;
// Using weak_ptr
if (auto temp = weak.lock()) {
cout << "Resource is alive: " << temp->getName() << endl;
} else {
cout << "Resource has been destroyed" << endl;
}
// Reset shared pointer
shared.reset();
cout << "After reset, shared use count: " << shared.use_count() << endl;
if (auto temp = weak.lock()) {
cout << "Resource is still alive" << endl;
} else {
cout << "Resource has been destroyed" << endl;
}
}
// Custom deleter for unique_ptr
void customDeleter(Resource* res) {
cout << "Custom deleter called for " << res->getName() << endl;
delete res;
}
int main() {
demonstrateUniquePtr();
demonstrateSharedPtr();
demonstrateWeakPtr();
// Using custom deleter
cout << "\n=== CUSTOM DELETER ===" << endl;
unique_ptr<Resource, decltype(&customDeleter)> customRes(
new Resource("Custom"), customDeleter);
customRes->use();
return 0;
}💻 C++ Practice Projects
Beginner Level
- 1Create a Bank Account Management System with classes
- 2Build a Simple Calculator with operator overloading
- 3Implement a Student Grade Management System
- 4Create a Vector Mathematics Library with operator overloading
- 5Build a Contact Management System with file I/O
Intermediate Level
- 1Develop a Template-based Stack and Queue library
- 2Create a Smart Pointer implementation from scratch
- 3Build a Matrix Class with arithmetic operations
- 4Implement a Custom String Class with dynamic memory
- 5Create a Generic Sorting Algorithm library
Advanced Level
- 1Build a Multithreaded Task Scheduler
- 2Create a Memory Pool Allocator with custom new/delete
- 3Implement a Simple Game Engine with polymorphism
- 4Develop a Template Metaprogramming library
- 5Build a Network Server with RAII and smart pointers
📋 C++ Quick Reference
Modern C++ Features
- •auto - Type deduction
- •lambda - Anonymous functions
- •range-based for - Simplified loops
- •smart pointers - Automatic memory management
- •move semantics - Efficient resource transfer
- •constexpr - Compile-time evaluation
- •nullptr - Type-safe null pointer
STL Containers
- •vector - Dynamic array
- •list - Doubly-linked list
- •map - Sorted key-value pairs
- •unordered_map - Hash table
- •set - Unique sorted elements
- •queue - FIFO container
- •stack - LIFO container
Master High-Performance Programming!
C++ remains the language of choice for performance-critical applications, game development, system software, and high-frequency trading. Its unique combination of high-level abstractions and low-level control provides unparalleled power and efficiency.
Modern C++ features make the language safer and more expressive while maintaining the performance that made C++ famous. Mastering C++ opens doors to cutting-edge software development careers.