C++
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C++
-
Section 4: Memory Management
-
Section 5: Templates and Generic Programming
-
Section 6: The Standard Template Library
-
Section 7: Modern C++ Features
-
Section 8: Error Handling
-
Section 9: Multithreading
-
Section 10: Operator Overloading and Type Conversion
-
Section 11: Advanced Topics
-
Section 12: Tooling and Build Systems
-
Section 13: Design Patterns in C++
-
Section 14: Interfacing with C and Systems Programming
-
Section 15: Networking and IPC Basics
-
Section 16: Graphics and Game Programming Basics
-
Section 17: The Boost Libraries
-
Section 18: Data Structures and Algorithms in C++
-
Section 19: Practical Projects
-
Section 20: More Concurrency Patterns
-
Section 21: More OOP and Design Practice
-
Section 22: File I/O and Streams
-
Section 23: More Standard Library
-
Section 24: Practice Exercises
-
Section 25: Interview and Algorithm Practice
-
Section 26: Compiler and Language Internals
-
Section 27: GUI and Application Frameworks Overview
-
Section 28: Testing and Quality Practices
-
Section 29: Numerics Library
-
Section 30: Concepts Library (C++20)
-
Section 31: Ranges Library (C++20) In Depth
-
Section 32: More Utility Library
80: Stacks and Queues via Container Adapters
I've seen this happen in countless code reviews: a developer tries to use a std::stack or a std::queue and then gets frustrated when they can't iterate through the elements with a loop or access a specific index. They assume that because it's in the Standard Template Library (STL), it's a first-class container like std::vector or std::list. It's a logical assumption, but it's fundamentally wrong.
The Myth: Stacks and Queues are Primary Containers
If you treat a stack like a vector, you'll hit a wall immediately. Take a look at this snippet. I've tried to do something very simple: print all the elements currently in the stack.
std::stack<int> myStack;
myStack.push(10);
myStack.push(20);
// This will fail to compile
for (auto it = myStack.begin(); it != myStack.end(); ++it) {
std::cout << *it << " ";
}
The compiler will scream at you. Why? Because std::stack doesn't have a begin() or end() method. It doesn't have iterators. You can't "peek" at the middle of the stack. If you could, it wouldn't be a stack—it would just be a vector that you're pretending is a stack.
The Reality: They are Container Adapters
In C++, std::stack and std::queue are container adapters. This is a fancy way of saying they are wrappers. They don't actually manage the memory or the data storage themselves; instead, they take an existing sequence container and "adapt" its interface to restrict what you can do with it.
Think of it like a security guard standing in front of a std::deque (which is the default underlying container). The guard says, "I don't care how many features the deque has; you're only allowed to put things on the top and take things off the top." By limiting the API, C++ ensures you don't accidentally break the LIFO (Last-In, First-Out) or FIFO (First-In, First-Out) logic of your data structure.
For a std::stack, you only get:
push(): Adds to the top.pop(): Removes from the top.top(): Looks at the top element.
For a std::queue, you get a slightly different flow:
push(): Adds to the back.pop(): Removes from the front.front(): Looks at the first element.back(): Looks at the last element.
Swapping the Underlying Engine
Here is the part most people miss: because these are adapters, you can choose which container they wrap. If you know your stack will grow very large and you want the cache-locality of a vector, you can tell the stack to use a std::vector instead of the default std::deque.
// Using a vector as the internal storage for a stack std::stack<int, std::vector<int>> vectorStack; // Using a list as the internal storage for a queue std::queue<int, std::list<int>> listQueue;I usually stick with the defaults unless I have a specific performance reason to change them.
std::dequeis a great middle-ground for both. But knowing you can change the engine is what separates someone who just knows the syntax from someone who understands how the STL is actually architected.
📋 Practical Task
Building a Browser History "Back" Button Simulator
You are tasked with simulating the "Back" button functionality of a web browser. In a real browser, as you visit pages, they are pushed onto a stack. When you hit "Back," the current page is popped off, and the previous page becomes the current one.
Requirements:
- Create a program that uses a
std::stackofstd::stringto store URLs. - Implement a loop that accepts user input:
"visit [url]": Pushes the URL onto the stack."back": Pops the current URL and displays the new top of the stack. If the stack becomes empty, notify the user that they have reached the start of their history."current": Displays the URL currently at the top of the stack."exit": Ends the program.
- Ensure your program handles the case where a user tries to go "back" or check "current" when the stack is empty to avoid runtime crashes.
There are no comments for now.