<map>
The <map>
header is part of the C++ Standard Template Library (STL) that provides the std::map
and std::multimap
container classes. These containers implement sorted associative containers, which store key-value pairs and keep them sorted by keys. std::map
ensures unique keys, while std::multimap
allows multiple entries with the same key.
std::map
(not in std::multimap
)[]
operator (only in std::map
)std::map
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, int> age_map;
// Inserting elements
age_map["Alice"] = 30;
age_map.insert({"Bob", 25});
age_map.insert(std::make_pair("Charlie", 35));
// Accessing elements
std::cout << "Alice's age: " << age_map["Alice"] << std::endl;
std::cout << "Bob's age: " << age_map.at("Bob") << std::endl;
// Checking if a key exists
if (age_map.count("David") == 0) {
std::cout << "David is not in the map" << std::endl;
}
// Iterating through the map
for (const auto& pair : age_map) {
std::cout << pair.first << " is " << pair.second << " years old" << std::endl;
}
// Size of the map
std::cout << "Map size: " << age_map.size() << std::endl;
return 0;
}
std::map
with string keys and integer values.[]
operator, insert()
, and make_pair()
.[]
and at()
methods.count()
method is used to check for key existence.std::map
#include <iostream>
#include <map>
#include <string>
// Custom comparator for case-insensitive string comparison
struct CaseInsensitiveCompare {
bool operator()(const std::string& a, const std::string& b) const {
return std::lexicographical_compare(
a.begin(), a.end(), b.begin(), b.end(),
[](char c1, char c2) { return std::tolower(c1) < std::tolower(c2); }
);
}
};
int main() {
std::map<std::string, int, CaseInsensitiveCompare> scores;
scores["Alice"] = 100;
scores["bob"] = 85;
scores["CHARLIE"] = 90;
// This will update "Alice" instead of creating a new entry
scores["aLiCe"] = 95;
for (const auto& pair : scores) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
return 0;
}
CaseInsensitiveCompare
for case-insensitive string comparison.std::multimap
#include <iostream>
#include <map>
#include <string>
int main() {
std::multimap<std::string, int> grades;
// Inserting multiple values for the same key
grades.insert({"Alice", 85});
grades.insert({"Bob", 90});
grades.insert({"Alice", 92});
grades.insert({"Charlie", 88});
grades.insert({"Bob", 95});
// Printing all entries
for (const auto& grade : grades) {
std::cout << grade.first << ": " << grade.second << std::endl;
}
// Finding all grades for a specific student
std::string student = "Bob";
auto range = grades.equal_range(student);
std::cout << "\nGrades for " << student << ":" << std::endl;
for (auto it = range.first; it != range.second; ++it) {
std::cout << it->second << std::endl;
}
// Counting entries for a key
std::cout << "\nNumber of grades for Alice: " << grades.count("Alice") << std::endl;
return 0;
}
std::multimap
allows multiple entries with the same key.equal_range()
is used to find all entries for a specific key.count()
returns the number of entries for a given key.#include <iostream>
#include <map>
#include <string>
void printMap(const std::map<std::string, int>& m) {
for (const auto& pair : m) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
std::cout << std::endl;
}
int main() {
std::map<std::string, int> inventory;
// Inserting elements
inventory["apple"] = 5;
inventory["banana"] = 8;
inventory["orange"] = 10;
std::cout << "Initial inventory:" << std::endl;
printMap(inventory);
// Modifying an element
inventory["apple"] = 7;
// Erasing an element
inventory.erase("orange");
std::cout << "After modifications:" << std::endl;
printMap(inventory);
// Finding an element
auto it = inventory.find("banana");
if (it != inventory.end()) {
std::cout << "Found " << it->first << " with quantity " << it->second << std::endl;
}
// Inserting with hint
auto hint = inventory.lower_bound("cherry");
inventory.insert(hint, {"cherry", 15});
std::cout << "After inserting cherry:" << std::endl;
printMap(inventory);
// Using emplace
inventory.emplace("grape", 20);
std::cout << "Final inventory:" << std::endl;
printMap(inventory);
return 0;
}
std::map
: insertion, modification, erasure, and searching.lower_bound()
is used to get a hint for efficient insertion.emplace()
is used for in-place construction of elements.find()
method is used to search for elements.#include <iostream>
#include <map>
#include <string>
// Custom comparator for pair<int, string>
struct PairCompare {
bool operator()(const std::pair<int, std::string>& lhs,
const std::pair<int, std::string>& rhs) const {
if (lhs.first != rhs.first)
return lhs.first < rhs.first;
return lhs.second < rhs.second;
}
};
int main() {
std::map<std::pair<int, std::string>, double, PairCompare> scores;
scores[{1, "Alice"}] = 95.5;
scores[{2, "Bob"}] = 89.0;
scores[{1, "Charlie"}] = 91.5;
scores[{3, "David"}] = 87.5;
for (const auto& entry : scores) {
std::cout << "Student ID: " << entry.first.first
<< ", Name: " << entry.first.second
<< ", Score: " << entry.second << std::endl;
}
// Finding a specific entry
auto it = scores.find({1, "Alice"});
if (it != scores.end()) {
std::cout << "\nFound: " << it->first.second
<< " (ID: " << it->first.first
<< ") with score " << it->second << std::endl;
}
return 0;
}
PairCompare
defines the ordering of the keys.Performance: Map operations have logarithmic complexity, which is efficient for most use cases but may be slower than unordered_map for very large datasets.
Memory Usage: Maps typically use more memory than unordered containers due to the overhead of maintaining the sorted structure.
Iterator Invalidation: Iterators and references to map elements remain valid after insertion or removal of other elements.
Comparison Requirements: The key type must support the <
operator or a custom comparator must be provided.
No Direct Data Access: Unlike vectors, map elements cannot be accessed directly by index.
The <map>
header in C++ provides the std::map
and std::multimap
containers, which are powerful tools for storing and manipulating key-value pairs:
std::map
) or multiple entries per key (std::multimap
).Maps are particularly useful when you need to maintain a sorted collection of key-value pairs with efficient lookup, insertion, and deletion operations. They are commonly used in scenarios such as dictionaries, indexes, and any situation where data needs to be associated with unique identifiers and kept in a specific order.
While maps provide powerful functionality, it's important to consider the specific requirements of your application. For cases where sorting is not necessary and faster average-case performance is desired, std::unordered_map
might be a better choice. Understanding the characteristics and proper usage of maps can significantly enhance the efficiency and clarity of C++ programs dealing with associative data.