A map is a list that can have a user-defined key type, and user defined data type, as opposed to an integer type and a user-defined data type.
Example:
1 2 3 4 5
|
//you could make the key_type a string, vector<>, etc... if you wanted to, it would work the same.
typedef unsigned int key_type;
typedef std::string data_type;
map<key_type, data_type> a_new_map;
|
You reference it using the key type. In your usual arrays and vectors, you use an integer, or unsigned integer. But with a map, you can use a string, vector, or any other data type with the appropriate operator (in this case,
operator==()
and
operator=()
) member function.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
struct user_info{
//arbitrary user information... just as an example
};
map<std::string, user_info> database({});
user_info user;
//set user to whatever...
database["John"] = user; //add the name and the information
//now we want to retrieve information...
if(database.find("John") != database.end())
{
//display information
user = database["John"];
}
|
This is useful for finding information quickly. I did a comparison between maps and iterating through a vector. The difference is very noticable: vector of 200,000 strings took 20 minutes to complete iteration, while the map only took 5-7 minutes. BIIIGG difference!
This is no substitute for hashing though, so keep in mind that if you require a reliable and effective hash, don't use maps!
So, how do we iterate through a STL object? Well, like we do all STL objects: we declare it's iterator. Objects that I commonly use iterators for are std::strings, std::vectors, and std::maps. There are many others, but these I use most often.
How do we declare an iterator though? Well, an iterator is declared by calling it through it's containing object.
Example:
1 2 3 4 5
|
std::string temps("HELLO WORLD!");
for(std::string::iterator it = temps.begin(); it != temps.end(); it++)
{
cout<< *it;
}
|
If you iterate through an object, you should use the
.end()
and
.begin()
member functions of that object. These functions return the beginning iterator, and end iterator respectively. The begin iterator returns an iterator pointing to the first valid index. The end iterator usually points to nothing (or NULL), and is returned when
.find()
does not find any matches.
For templated objects, you will have to give the template type. Lists, maps and vectors are templated objects.
For example:
1 2 3 4 5 6 7
|
std::vector<int> alist({});
for(short x = 0; x < 100; x++) alist.push_back(x);
for(std::vector<int>::iterator it = alist.begin(); it != alist.end(); it++)
{
cout<< *it<< endl;
}
|
Iterators are objects too. You can declare them anywhere, but they have to be of the type you declare them:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
std::string s("Hello World");
std::vector<char> vec({'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd'});
std::vector<char>::iterator v_it(vec.begin());
/* WRONG WAY */
for(; v_it != s.end(); it++); //v_it is a vector iterator, not a string iterator!
/* Right way: */
for(; v_it != vec.end(); it++)
{
cout<< *it;
}
|
So, why use iterators? Because they provide consistency and provide a base for some algorithms. For some STL objects they are also more efficient than indices! It depends on the object you use the iterator for, and what you do with the iterator.
Best of luck.