For working professionals
For fresh graduates
More
Explore C++ Tutorials: Explori…
1. The Ultimate C++ Guide: C++ Tutorial for Beginners
2. Application of C++
3. C++ Hello World Program
4. C++ Variable
5. Reference Variable in C++
6. Function Overloading in C++
7. Functions in C++
8. Pointer in C++
9. Data Types in C++
10. C++ for Loop
11. While Loop in C++
12. C++ Lambda
13. Loop in C++
14. Switch Case in C++
15. Array in C++
16. Strings in C++
17. Substring in C++
18. Class and Object in C++
19. Constructor in C++
20. Copy Constructor in C++
21. Destructor in C++
22. Multiple Inheritance in C++
23. Encapsulation in C++
24. Single Inheritance in C++
25. Friend Class in C++
26. Hierarchical Inheritance in C++
27. Virtual Base Class in C++
28. Abstract Class in C++
29. Vector in C++
30. Map in C++
31. Pair in C++
32. Initialize Vector in C++
33. Iterators in C++
34. Queue in C++
35. Priority Queue in C++
36. Stack in C++
Now Reading
37. ifstream in C++
38. Exception Handling in C++
39. Memory Management in C++
40. Templates in C++
41. Type Conversion in C++
42. Enumeration in C++
43. Namespace in C++
44. Set Precision in C++
45. Stringstream in C++
46. Recursion in C++
47. Random Number Generator in C++
48. C++ Shell
49. Setw in C++
50. Multithreading in C++
51. Atoi in C++
52. Call by Value and Call by Reference in C++
53. Difference Between C and C++
54. C# vs C++
55. C++ GUI
56. C++ Game Code
57. Class in C++
58. C++ Header Files
59. Power Function in C++
60. Data Hiding in C++
61. Inline Function in C++
62. Getline Function in C++
63. Cin in C++
64. Printf in C++
65. Struct in C++
66. C++ List
67. static_cast in C++
68. C++ Comments
69. Structures in C++
70. C++ Standard Template Library (STL)
71. Virtual Function in C++
72. Sorting in C++
73. Polymorphism in C++
74. Oops Concepts in C++
75. Converting Integers to Strings in C++
76. Differences Between Break and Continue
The stack in C++ is a fundamental data structure with a Last-In, First-Out (LIFO) access pattern. This characteristic makes it well-suited for a wide range of applications, including function call management, expression evaluation, and backtracking algorithms.
The Standard Template Library (STL) in C++ provides a convenient implementation of the stack data structure in the form of the std::stack container adaptor. I will delve into the inner workings of stacks in this tutorial and we will explore their use in various scenarios. We will also discuss how to optimize their performance.
Let’s dive in.
A stack is a linear data structure that adheres to this LIFO rule. We can only access the top element, adding new elements (pushing) or removing existing ones (popping) exclusively from this top position. We can think of it like a spring-loaded tray dispenser where we can only take from the top, and when we add a tray, it goes on top of the others.
I would like to mention that the LIFO principle is a powerful concept that enables a wide range of algorithms and programming techniques.
Stacks are behind many computational tasks in C++. They might seem simple, but their LIFO behavior makes them indispensable in various domains:
The Standard Template Library (STL) offers a pre-built solution, the std::stack container adaptor when it comes to using stacks. This is a lifesaver because it means that we do not have to write our own stack implementation from scratch. We get all the benefits of a well-designed stack without the extra work.
We can think of container adaptors like a costume change for existing data structures. std::stack takes a regular container (like a vector, deque, or list) and dresses it up to act like a stack. This gives us the core stack functionality (push, pop, top) while letting us choose the underlying storage that best fits our needs. It's like having a wardrobe full of stack outfits for different occasions!
The brilliance of std::stack is its adaptability. By default, it uses a std::deque as its underlying container, which offers a nice balance of efficient insertion and removal at both ends. But we are not locked into that choice. We can easily swap it out for a std::vector (if you prefer contiguous storage) or a std::list (if we need frequent insertions/deletions throughout the stack).
This flexibility means we can fine-tune the performance of our stack depending on how we plan to use it. It's like having a Swiss Army knife for stack implementation.
The beauty of std::stack is its flexibility. We can choose one of three common container types as the backbone of our stack:
Pros:
Cons:
Pros:
Cons:
Pros:
Cons:
Here is how we can choose the right container:
Here's how we create std::stack objects with different data types and initialize them with values:
Code:
#include <iostream>
#include <stack>
#include <vector>
int main() {
// Declare and initialize a stack of integers
std::stack<int> intStack;
intStack.push(10);
intStack.push(20);
intStack.push(30);
// Declare and initialize a stack of strings
std::stack<std::string> stringStack;
stringStack.push("apple");
stringStack.push("banana");
stringStack.push("cherry");
// Declare a stack of a custom object type
struct Person {
std::string name;
int age;
};
std::stack<Person> personStack;
// Create some Person objects and push them onto the stack
Person person1 = {"Alice", 30};
Person person2 = {"Bob", 25};
personStack.push(person1);
personStack.push(person2);
std::cout << "Integer stack top: " << intStack.top() << std::endl;
std::cout << "String stack top: " << stringStack.top() << std::endl;
std::cout << "Person stack top name: " << personStack.top().name << std::endl; // Access the name of the top Person object
}
If you wish to learn how to code in C++ like the above stack in C++ program, you can check out upGrad’s software engineering courses.
Let us explore some important stack operations.
The push() operation takes an element as input and adds it to the top of the stack. Internally, this typically involves:
If the underlying container is full, pushing a new element leads to a stack overflow. std::stack built on std::vector or std::deque might handle this by automatically resizing, but this can be costly. std::stack built on std::list won't overflow but might consume excessive memory.
Handling:
The pop() operation removes the top element from the stack.
It typically involves:
Calling pop() on an empty stack is an error (stack underflow). std::stack might throw an exception in this case.
Handling:
The top() function returns a reference to the topmost element without removing it. This allows us to inspect or modify the top element without altering the stack's structure.
Like pop(), calling top() on an empty stack is an error.
Handling:
The empty() function is a boolean check. It returns true if the stack contains no elements and false otherwise. We can use it to control loop conditions or avoid underflow errors.
The size() function returns the number of elements currently stored in the stack.
Here are the member types we need for stack in C++:
Example stack push pop program in C++:
Code:
#include <iostream>
#include <stack>
int main() {
std::stack<int> numbers;
numbers.push(10);
numbers.push(20);
std::cout << "Top element: " << numbers.top() << std::endl; // Output: 20
numbers.pop();
std::cout << "New top element: " << numbers.top() << std::endl; // Output: 10
}
I feel that choosing the right stack implementation involves balancing performance, memory usage, and the specific requirements of our application. In most cases, the std::stack with its default std::deque container is a solid choice, but if we have very specific performance needs, exploring specialized libraries might be worthwhile.
In general, the core stack operations offered by std::stack exhibit constant time complexity, denoted as O(1). This means that the time it takes to push, pop, or access the top element is independent of the size of the stack.
The time complexity assumes that the underlying container (vector, deque, or list) also supports O(1) insertion and removal at the end. While this is generally true, there might be edge cases where the container needs to resize, leading to a slightly higher (but amortized constant) time complexity.
The choice of the underlying container can significantly impact memory usage:
Potentially less memory overhead initially, as elements are stored contiguously. However, resizing can lead to reallocation and copying of elements, increasing memory usage temporarily.
Offers a good balance, as it avoids the frequent reallocation issues of vectors but still allows for relatively efficient memory usage.
Typically has the highest memory overhead per element due to storing pointers for the linked list structure. It is ideal if we anticipate a very large stack size or frequent insertions/deletions throughout the stack.
While std::stack covers most general use cases, specialized libraries exist for scenarios where performance is absolutely critical:
While stack in cpp is powerful, it are not always the right tool for the job. Let us compare stack functions in C++ to using other common data structures for our functions:
You can trying to implement stack in C++ using array for exploring how the stack function can work with different data structures. You can also similarly implement stack in C++ using linked lists and queues.
The std::stack container in C++ is a versatile and efficient tool for managing data in a LIFO manner. By understanding its underlying principles, exploring its various applications, and considering performance optimization techniques, we can effectively leverage stacks to solve a wide array of programming challenges.
While simple in concept, stacks play a crucial role in numerous algorithms and computational tasks, highlighting their significance in the world of software development. If you wish to learn programming languages such as C++, you can check out upGrad’s computer science programs such as the Master’s in Computer Science Program.
A stack in C++ is a LIFO (Last-In, First-Out) data structure where elements are added (pushed) and removed (popped) from the same end, known as the top.
We can implement a stack using an array or a linked list, or we can simply use the std::stack container adaptor from the Standard Template Library (STL).
The basic operations are:
Include the <stack> header and then create a stack object like this: std::stack<data_type> stack_name; (replace data_type with the type of elements we want to store).
Yes, C++ provides the std::stack container in the <stack> header as part of the STL.
Yes, you can use custom objects with the std::stack as long as your object type supports copy construction.
Use a stack when you need LIFO behavior, like in function call tracking, expression evaluation, backtracking algorithms, or undo/redo functionality.
In general, all stack operations (push(), pop(), top(), empty(), size()) have a time complexity of O(1) in C++.
Author
Start Learning For Free
Explore Our Free Software Tutorials and Elevate your Career.
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.