Stacks in C++ STL

A stack is a container that follows the Last In, First Out (LIFO) principle. The last element you put in is the first one that comes out. Think of a stack of plates in a cafeteria — you always pick up the plate on top, and you always place a new plate on top. You never reach into the middle.

C++ provides a ready-to-use stack through the Standard Template Library (STL) in the <stack> header. You do not need to build one from scratch.

LIFO Principle — Visual Diagram

PUSH order: 10, 20, 30
Stack grows upward:

  TOP → [ 30 ]   ← pushed last, popped first
        [ 20 ]
BOTTOM→ [ 10 ]   ← pushed first, popped last

POP order: 30, 20, 10

Declaring a Stack

#include <stack>
using namespace std;

stack<int>    s;        // stack of integers
stack<string> words;   // stack of strings
stack<double> prices;  // stack of doubles

Core Stack Operations

OperationMethodDescription
Pushs.push(val)Add element to the top
Pops.pop()Remove top element (no return value)
Tops.top()View the top element without removing
Empty checks.empty()Returns true if stack has no elements
Sizes.size()Returns number of elements

Basic Stack Example

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> s;

    s.push(10);
    s.push(20);
    s.push(30);

    cout << "Top: " << s.top() << endl;   // 30
    cout << "Size: " << s.size() << endl;  // 3

    s.pop();  // removes 30
    cout << "After pop, Top: " << s.top() << endl;  // 20

    return 0;
}

Output:

Top: 30
Size: 3
After pop, Top: 20

Iterating Through a Stack

STL stack does not support iterators or index access. To visit every element, you pop them one by one until the stack is empty.

#include <iostream>
#include <stack>
using namespace std;

int main() {
    stack<int> s;
    s.push(5);
    s.push(15);
    s.push(25);
    s.push(35);

    cout << "Stack contents (top to bottom): ";
    while (!s.empty()) {
        cout << s.top() << " ";
        s.pop();
    }
    cout << endl;

    return 0;
}

Output:

Stack contents (top to bottom): 35 25 15 5

Real-World Example: Undo Feature

One of the most common uses of a stack in software is implementing the Undo feature in text editors. Every action you take gets pushed onto a stack. Pressing Undo pops the last action and reverses it.

#include <iostream>
#include <stack>
#include <string>
using namespace std;

int main() {
    stack<string> actions;

    actions.push("Typed 'Hello'");
    actions.push("Bold text");
    actions.push("Changed font size");
    actions.push("Inserted image");

    cout << "Action history (most recent first):" << endl;
    int step = 1;
    while (!actions.empty()) {
        cout << "Undo step " << step++ << ": " << actions.top() << endl;
        actions.pop();
    }

    return 0;
}

Output:

Action history (most recent first):
Undo step 1: Inserted image
Undo step 2: Changed font size
Undo step 3: Bold text
Undo step 4: Typed 'Hello'

Real-World Example: Balanced Brackets Checker

Stacks are widely used to check whether brackets in an expression are balanced. Every opening bracket is pushed onto the stack. Every closing bracket is compared against the top of the stack.

#include <iostream>
#include <stack>
#include <string>
using namespace std;

bool isBalanced(string expr) {
    stack<char> s;

    for (char ch : expr) {
        if (ch == '(' || ch == '{' || ch == '[') {
            s.push(ch);
        } else if (ch == ')' || ch == '}' || ch == ']') {
            if (s.empty()) return false;
            char top = s.top();
            s.pop();
            if ((ch == ')' && top != '(') ||
                (ch == '}' && top != '{') ||
                (ch == ']' && top != '[')) {
                return false;
            }
        }
    }
    return s.empty();
}

int main() {
    cout << isBalanced("{[()]}") << endl;   // 1 (true)
    cout << isBalanced("{[(])}") << endl;   // 0 (false)
    cout << isBalanced("((())") << endl;    // 0 (false)
    return 0;
}

Output:

1
0
0

Stack with String Elements

#include <iostream>
#include <stack>
#include <string>
using namespace std;

int main() {
    stack<string> pages;

    pages.push("Home");
    pages.push("Products");
    pages.push("Cart");
    pages.push("Checkout");

    cout << "Browser back navigation:" << endl;
    while (!pages.empty()) {
        cout << "Current page: " << pages.top() << endl;
        pages.pop();
    }

    return 0;
}

Output:

Browser back navigation:
Current page: Checkout
Current page: Cart
Current page: Products
Current page: Home

This mimics how a browser's back button works — pages you visited are stored in a stack, and pressing back pops the current page to return to the previous one.

Underlying Container of STL Stack

The STL stack is a container adaptor — it wraps another container internally. By default it uses deque, but you can change it.

#include <stack>
#include <vector>
#include <list>
using namespace std;

stack<int>                    s1;  // default: uses deque
stack<int, vector<int>>       s2;  // uses vector internally
stack<int, list<int>>         s3;  // uses list internally

Common Stack Use Cases

Use CaseHow Stack Helps
Undo / RedoEach action pushed; undo pops last action
Bracket matchingPush open brackets, pop on close
Browser history (back)Each page pushed; back button pops
Function call trackingCPU uses a call stack for nested function calls
Expression evaluationOperators and operands managed with stacks
Depth-first search (DFS)Stack tracks nodes to visit in graph traversal

Key Takeaways

  • A stack follows LIFO — the last element in is the first element out.
  • Use push() to add, pop() to remove, and top() to read the top element.
  • pop() does not return the removed value — always read with top() first.
  • Always check empty() before calling top() or pop() to avoid undefined behavior.
  • The STL stack is a container adaptor that wraps deque by default.

Leave a Comment

Your email address will not be published. Required fields are marked *