CLOSE
🛠️ Settings

C++ STL

The C++ STL is essentially a built-in library that provides a wide range of template classes and functions to handle common programming tasks. It offers high-performance, reusable components that integrate easily into your programs. Using the STL means you don't have to build data structures from scratch, so you can concentrate more on developing your application's logic.

Key Components of STL

1️⃣ Containers

These are the data structures that store collections of objects, such as vector, list, deque, set, map, and more.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    numbers.push_back(6); // Add an element

    // Print all elements in the vector
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}

2️⃣ Iterators

They act like pointers to traverse through the elements in container, providing a common interface to access and navigate the data.

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {10, 20, 30, 40, 50};

    // Use an iterator to traverse the vector
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    return 0;
}

3️⃣ Algorithms

A set of functions (like sort, search, and transform) that operate on containers using iterators, helping us perform common operations without writing custom code.

#include <iostream>
#include <vector>
#include <algorithm> // For std::sort

int main() {
    std::vector<int> numbers = {40, 10, 50, 20, 30};

    // Sort the vector in ascending order
    std::sort(numbers.begin(), numbers.end());

    // Print the sorted vector
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}

4️⃣ Function Objects (Functors)

Objects that can be treated as though they are functions or function pointers, often used with STL algorithms to customize behavior.

#include <iostream>
#include <vector>
#include <algorithm> // For std::sort

// Define a functor for reverse sorting
struct ReverseCompare {
    bool operator()(int a, int b) {
        return a > b; // Reverse order: larger numbers come first
    }
};

int main() {
    std::vector<int> numbers = {40, 10, 50, 20, 30};

    // Use the functor for sorting in descending order
    std::sort(numbers.begin(), numbers.end(), ReverseCompare());

    // Print the sorted vector
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}

5️⃣ Allocators

These manage the allocation and deallocation of memory for container elements, abstracting the memory management process.

#include <iostream>
#include <vector>
#include <memory> // For std::allocator

int main() {
    // Create a vector using the default allocator explicitly
    std::vector<int, std::allocator<int>> numbers = {1, 2, 3, 4, 5};
    numbers.push_back(6);

    // Print the vector
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}

Containers

1️⃣ Pair (std::pair)

A pair is a simple container that holds two values which may be of different types (heterogeneous objects) as a single unit. This is particularly used to associate two values together, such as when storing key-value pairs. The pair can store values of any data type, and the values can be accessed directly using first and second members.

Example Code:

#include <iostream>
#include <utility> // Required for std::pair

using namespace std;

int main() {
    pair<int, string> p;
    p.first = 42;
    p.second = "Jat";

    cout << p.first << " " << p.second << endl; // Output: 42 Jat
    return 0;
}

Initialization:

pair<int, string> p1(1, "apple");
pair<int, string> p2 = make_pair(2, "banana");

Access Elements:

cout << p1.first;   // 1
cout << p1.second;  // "apple"

Common Use Cases:

  • Return two values from a function.
  • Store key-value pairs.
  • Use in sorting problems with custom criteria.
  • As elements in STL containers like vector<pair<>>.

Comparison & Sorting:

Pairs are compared lexicographically.

pair<int, int> a = {1, 2};
pair<int, int> b = {1, 3};
cout << (a < b); // true because 2 < 3

Sorting a vector of pairs:

vector<pair<int, int>> v = {{1, 3}, {2, 2}, {1, 2}};
sort(v.begin(), v.end()); // sorts by first, then second

Pair in Containers:

vector<pair<int, string>> v;
v.push_back({1, "A"});
v.emplace_back(2, "B");

for (auto [x, y] : v) {
    cout << x << " " << y << endl;
}

Nested Pairs:

pair<int, pair<int, int>> p = {1, {2, 3}};
cout << p.second.first; // 2

Use in Maps:

map<int, string> m;
for (auto p : m) {
    cout << p.first << ": " << p.second << endl;
}

Tips:

  • Use structured bindings (auto [a, b]) for clarity.

2️⃣ Vector (std::vector)

A vector is a dynamic array in C++ STL. It can grow or shrink in size automatically and supports random access.

vector<int> v = {1, 2, 3, 4};

Basic Syntax:

#include <vector>
#include <iostream>

using namespace std;

int main() {
    vector<int> v;         // empty vector
    v.push_back(10);       // add element at end
    v.push_back(20);

    cout << v[0];          // access like array
    cout << v.at(1);       // bounds-checked access
}

Initialization:

vector<int> v1;                           // empty
vector<int> v2(5);                        // 5 elements initialized to 0
vector<int> v3(5, 10);                    // 5 elements initialized to 10
vector<int> v4 = {1, 2, 3};               // initializer list
vector<int> v5(v4);                       // copy constructor
vector<int> v6(v4.begin(), v4.begin()+2); // partial copy

Traversing a Vector:

vector<int> v = {1, 2, 3};

// Index-based
for (int i = 0; i < v.size(); ++i) cout << v[i];

// Range-based
for (int x : v) cout << x;

// Iterator
for (auto it = v.begin(); it != v.end(); ++it) cout << *it;

push_back:

The push_back function adds a new element at the end of the vector. This is often used to append elements in a loop or based on certain conditions.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {1, 2, 3};
            v.push_back(4);
            v.push_back(5);
            for (int i : v) {
                cout << i << " ";
            }
            return 0;
        }

pop_back():

Remove the last element.

front():

The front function returns a reference to the first element in the vector. This is useful when we need to access the starting element without modifying the vector.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            cout << "Front element: " << v.front();
            return 0;
        }

back():

The back function returns a reference to the last element in the vector. It’s typically used when the last inserted element needs to be accessed or modified.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            cout << "Back element: " << v.back();
            return 0;
        }

iterator:

Vectors support iterators, which allow traversal through the elements in the vector. Iterators behave like pointers and can be used for accessing elements or performing operations on the vector.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            for (vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
                cout << *it << " ";
            }
            return 0;
        }

for each:

The for_each loop in C++11 allows for a simpler way to iterate over vectors. It simplifies the syntax and enhances code readability.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            for (int i : v) {
                cout << i << " ";
            }
            return 0;
        }
 // Output:
 10 20 30

erase():

The erase function removes an element from the vector by a position causing all subsequent elements to be shifted one position to the left.This helps reduces the size of the vector by one.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            v.erase(v.begin() + 1);
            for (int i : v) {
                cout << i << " ";
            }
            return 0;
        }
// Output:
10 30

insert():

The insert function inserts elements at a specified position in the vector. It shifts all elements at and after the insertion point to the right, increasing the vector's size.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 30};
            v.insert(v.begin() + 1, 20);
            for (int i : v) {
                cout << i << " ";
            }
            return 0;
        }
// Output:
10 20 30

size():

The size function returns the number of elements in the vector. This is helpful in loops or conditions where the vector’s length is a determining factor.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            cout << "Size of vector: " << v.size();
            return 0;
        }
        
// Size of vector: 3

Access Element:

Elements in a vector can be accessed using the [] operator or the at() method.

  • []: does not check for array bounds.
  • at(): checks for the array bounds.
#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            cout << "Element at index 1: " << v[1];
            cout << "Element at index 1: " << v.at(1);
            return 0;
        }
// Output:
Element at index 1: 10
Element at index 1: 10

swap():

The swap function swaps the contents of two vectors. This is an efficient way to swap large vectors since it only swaps the internal pointers rather than copying elements.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v1 = {1, 2, 3};
            vector<int> v2 = {4, 5, 6};
            swap(v1, v2);
            for (int i : v1) {
                cout << i << " ";
            }
            return 0;
        }

clear():

The clear function removes all elements from the vector, making it empty. It reduces the vector's size to zero but does not free the memory allocated by the vector.

#include <bits/stdc++.h>
        using namespace std;
        
        int main() {
            vector<int> v = {10, 20, 30};
            v.clear();
            cout << "Size after clear: " << v.size();
            return 0;
        }

Vector of Pairs or structs:

vector<pair<int, int>> vp = {{1, 2}, {3, 4}};
for (auto [x, y] : vp) cout << x << " " << y << endl;

2D Vectors (Matrix Style):

vector<vector<int>> mat(3, vector<int>(4, 0)); // 3x4 matrix initialized to 0

// Accessing
mat[0][1] = 5;

// Traversal
for (auto row : mat) {
    for (int val : row) {
        cout << val << " ";
    }
    cout << endl;
}