C++ Standard Template Library Overview
The C++ Standard Template Library (STL) is a core component of the language, offering generic classes and functions for implementing data structures and algorithms. It consists of five main components:
- Containers: Data structures for storing collections of elements.
- Algorithms: Functions for operations like sorting, searching, and modifying data.
- Iterators: Objects that enable traversal of container elements.
- Function Objects: Objects that behave like functions.
- Adapters: Components that modify interfaces of containers, iterators, or function objects.
This article focuses on containers, algorithms, and iterators, covering common usage patterns.
Containers
STL containers are categorized into three types: sequence containers, associative containers, and unordered associative containers.
Sequence Containers
vector: A dynamic array that allows resizing and efficient random access.
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30, 40, 50};
nums.push_back(60);
std::cout << "Size: " << nums.size() << std::endl;
nums.resize(8);
for (int val : nums) {
std::cout << val << " ";
}
return 0;
}
queue: A container adapter implementing FIFO (First-In-First-Out) behavior.
#include <queue>
#include <iostream>
int main() {
std::queue<int> q;
q.push(100);
q.push(200);
std::cout << "Front: " << q.front() << std::endl;
q.pop();
while (!q.empty()) {
std::cout << q.front() << " ";
q.pop();
}
return 0;
}
stack: A container adapter implementing LIFO (Last-In-First-Out) behavior.
#include <stack>
#include <iostream>
int main() {
std::stack<int> stk;
stk.push(5);
stk.push(15);
std::cout << "Top: " << stk.top() << std::endl;
stk.pop();
std::cout << "Empty? " << stk.empty() << std::endl;
return 0;
}
deque: A double-ended queue supporting insertion and deletion at both ends.
#include <deque>
#include <iostream>
int main() {
std::deque<char> dq = {'a', 'b', 'c'};
dq.push_front('z');
dq.push_back('d');
for (char ch : dq) {
std::cout << ch << " ";
}
return 0;
}
list: A doubly-linked list allowing efficient insertions and deletions.
#include <list>
#include <iostream>
int main() {
std::list<double> lst = {1.1, 2.2, 3.3};
lst.push_front(0.5);
lst.push_back(4.4);
for (double num : lst) {
std::cout << num << " ";
}
return 0;
}
Associative Containers
set: Stores unique elements in sorted order.
#include <set>
#include <iostream>
int main() {
std::set<int> s = {5, 3, 8, 3, 2};
s.insert(7);
s.erase(3);
std::cout << "Contains 2? " << s.count(2) << std::endl;
for (int elem : s) {
std::cout << elem << " ";
}
return 0;
}
map: Stores key-value pairs with unique keys in sorted order.
#include <map>
#include <iostream>
int main() {
std::map<std::string, int> ageMap;
ageMap["Alice"] = 30;
ageMap["Bob"] = 25;
std::cout << "Alice's age: " << ageMap["Alice"] << std::endl;
std::cout << "Size: " << ageMap.size() << std::endl;
return 0;
}
Unordered Associative Containers
These containers do not maintain element order, offering faster average performance.
#include <unordered_set>
#include <unordered_map>
int main() {
std::unordered_set<int> us = {9, 1, 8, 2};
std::unordered_map<int, std::string> um;
um[101] = "Item A";
return 0;
}
Algorithms
STL provides generic algorithms that work with various containers.
- Sorting:
std::sortandstd::stable_sortarrange elements in a range.
#include <algorithm>
#include <vector>
#include <iostream>
bool descending(int x, int y) {
return x > y;
}
int main() {
std::vector<int> vals = {34, 12, 67, 23};
std::sort(vals.begin(), vals.end());
std::sort(vals.begin(), vals.end(), descending);
for (int v : vals) {
std::cout << v << " ";
}
return 0;
}
- Searching:
std::findlocates an element in a range.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> data = {11, 22, 33, 44};
auto pos = std::find(data.begin(), data.end(), 33);
if (pos != data.end()) {
std::cout << "Found at index: " << (pos - data.begin()) << std::endl;
}
return 0;
}
- Set Operations:
std::set_unionandstd::set_intersectioncombine or intersect sorted ranges.
#include <algorithm>
#include <vector>
#include <iterator>
int main() {
std::vector<int> a = {1, 3, 5};
std::vector<int> b = {3, 4, 6};
std::vector<int> unionResult, intersectResult;
std::set_union(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(unionResult));
std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersectResult));
return 0;
}
- Reversing:
std::reverseinverts the order of elements in a range.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<char> letters = {'x', 'y', 'z'};
std::reverse(letters.begin(), letters.end());
for (char c : letters) {
std::cout << c << " ";
}
return 0;
}
- Removing Duplicates:
std::uniqueeliminates consecutive duplicates in a sorted range.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> seq = {2, 2, 3, 4, 4, 5};
auto newEnd = std::unique(seq.begin(), seq.end());
seq.erase(newEnd, seq.end());
for (int n : seq) {
std::cout << n << " ";
}
return 0;
}
- Binary Search Bounds:
std::lower_boundandstd::upper_boundfind positions in sorted ranges.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> sorted = {10, 20, 30, 40, 50};
auto lb = std::lower_bound(sorted.begin(), sorted.end(), 25);
auto ub = std::upper_bound(sorted.begin(), sorted.end(), 30);
std::cout << "Lower bound: " << (lb - sorted.begin()) << std::endl;
std::cout << "Upper bound: " << (ub - sorted.begin()) << std::endl;
return 0;
}
Iterators
Iterators provide a uniform way to traverse container elements, acting as generalized pointers.
Common iterator operations include begin() to get the start, end() for the past-the-end position, incrementing with ++, and dereferencing with *.
#include <vector>
#include <iostream>
int main() {
std::vector<int> items = {6, 7, 8, 9, 10};
for (auto it = items.begin(); it != items.end(); ++it) {
std::cout << *it << " ";
}
return 0;
}