下标操作,说白了, 就是一种映射关系。 高中的数列, C语言中的内置数组, 都应该学过吧, 这些都可以理解为下标操作。
我们知道, 典型的顺序容器中, string, vector, deque都是支持下标操作的, 当然, 很多地方都说支持随机访问, 其实这个随机访问实际上就是只下标操作。
对于关联容器而言, set, multiset中的元素就是其关键字本身, 所以什么映射关系, 自然就没有下标操作了。 multimap也是没有下标操作的, 因为相同的关键字可能对应不同的值。 而map则特别, 对于一个给定的关键字, 有唯一的一个值和它对应, 非常类似于你我高中学过的数列, 所以, map只是下标操作也是合情合理的。
但是, map的下标操作与顺序容器的下标操作却有不同的地方, 我理解, 区别主要如下:
1. vector的下标操作不会让vector元素增加, 但map的下标操作却可以。
2. 对于vector, *it与v[i]是等价的, 但是, 在map中, *it得到的是一个value_type, 而m[i]得到的是mapped_type, 不要被这个吓唬住, 我等下回仔细说明。
好, 废话也说了不少, 直接玩代码吧:
#pragma warning(disable : 4786) #include <map> #include <string> #include <iostream> using namespace std; int main() { map<string, int> m; m["good"]; m["zoo"] = 10; map<string, int>::iterator it; for(it = m.begin(); it != m.end(); it++) { cout << it->first << " " << it->second << endl; } return 0; }结果为:
good 0
zoo 10
我们可以看到, 当原来的map中没有关键字"good"和"zoo"时, 硬生生地增加了两对元素。
好, 继续看代码:
#pragma warning(disable : 4786) #include <map> #include <string> #include <iostream> using namespace std; int main() { map<string, int> m; m["good"]; m["zoo"] = 10; m["zoo"]++; cout << m["zoo"] << endl; // m["zoo"]的类型是int类型 map<string, int>::iterator it; for(it = m.begin(); it != m.end(); it++) { cout << (*it).first << " " << (*it).second << endl; // *it的类型是一个"string到int的映射对"类型 } return 0; }结果为:
11
good 0
zoo 11
不得不说, map的下标操作非常方便, 从此, 我们有了更加强大的数组: 关联数组。
我之前已经说过, 数组的本质就是映射, 也给出过好几个map的重要应用的例子, 现在回头看, 果真如此啊!
最后, 让我们一起来欣赏一下map这个关联数组的一个经典应用:统计单词数目
#pragma warning(disable : 4786) #include <map> #include <string> #include <fstream> #include <iostream> using namespace std; int main() { ifstream cin("test.txt"); // 这个cin会屏蔽掉std::cin if(!cin) { return 1; } map<string, int> m; string word; while(cin >> word) { m[word]++; // 非常非常经典啊, 我被map折服得五体头地 } map<string, int>::iterator it; for(it = m.begin(); it != m.end(); it++) { cout << (*it).first << " " << (*it).second << endl; } return 0; }经测试, ok.