August 11, 2025

Mastering std::list in C++

Posted on August 11, 2025  •  3 minutes  • 622 words

The std::list container in C++ is part of the Standard Template Library (STL) and implements a doubly linked list.
It allows fast insertion and deletion anywhere in the sequence, but does not allow random access like vectors.

YouTube video thumbnail

Key Characteristics

  • Doubly linked list implementation.
  • Elements are not stored contiguously in memory.
  • Fast insertion and deletion at any position — O(1) if the iterator is known.
  • No random access (no operator[] or direct indexing).
  • Iterators remain valid even after insertion or deletion (except for the erased element).
  • Maintains insertion order.

Syntax

#include <list>

// Creates an empty list of integers
std::list<int> l;

Basic Operations

1. Insertion

#include <iostream>
#include <list>

int main() 
{
    std::list<int> l;

    l.push_back(10);   // Insert at end
    l.push_front(5);   // Insert at front
    l.insert(++l.begin(), 7); // Insert at specific position

    for (int x : l) 
    {
        std::cout << x << " ";
    }
}

Output:

5 7 10

2. Deletion

l.pop_back();         // Remove last element
l.pop_front();        // Remove first element
l.erase(++l.begin()); // Remove element at position
l.remove(7);          // Remove all occurrences of 7

3. Accessing Elements

std::cout << "Front: " << l.front() << "\n";
std::cout << "Back: " << l.back() << "\n";

You cannot do l[0] because lists do not support random access.


4. Size and Empty Check

std::cout << "Size: " << l.size() << "\n";
if (l.empty()) 
{
    std::cout << "List is empty\n";
}

Iterating Over a List

for (auto it = l.begin(); it != l.end(); ++it) 
{
    std::cout << *it << " ";
}

Using range-based loop:

for (int val : l) 
{
    std::cout << val << " ";
}

Splicing Lists

The splice() function transfers elements from one list to another without copying.

std::list<int> l1 = {1, 2, 3};
std::list<int> l2 = {4, 5};

l1.splice(l1.end(), l2); // Move all from l2 to l1

After splicing:
l1 = {1, 2, 3, 4, 5}, l2 = {}


Sorting and Removing Duplicates

std::list<int> l = {5, 2, 5, 1, 2, 3};

l.sort();       // Sorts the list
l.unique();     // Removes consecutive duplicates (must be sorted first)

for (int x : l) 
    std::cout << x << " ";

Output:

1 2 3 5

Reverse a List

l.reverse();

Common Member Functions

Function Description
push_back(val) Adds element to the end.
push_front(val) Adds element to the front.
pop_back() Removes last element.
pop_front() Removes first element.
insert(pos, val) Inserts element at given position.
erase(pos) Removes element at given position.
remove(val) Removes all occurrences of a value.
sort() Sorts the list.
unique() Removes consecutive duplicates.
reverse() Reverses the list.
splice(pos, other) Moves elements from another list.
clear() Removes all elements.

Example: Merging Two Sorted Lists

#include <iostream>
#include <list>

int main() 
{
    std::list<int> l1 = {1, 3, 5};
    std::list<int> l2 = {2, 4, 6};

    l1.merge(l2);

    for (int x : l1) 
        std::cout << x << " ";
}

Output:

1 2 3 4 5 6

Performance Notes

  • Insertion/Deletion: O(1) if position is known.
  • No random access — iterating is O(n).
  • More memory overhead than vectors due to extra pointers.
  • Best when you need frequent insertions/deletions in the middle.

Summary

  • Use std::list when you need frequent insertions/deletions and don’t require random access.
  • Iterators remain valid after modifications.
  • Supports advanced operations like splice, merge, sort, and unique.
Follow me

I work on everything coding and share developer memes