【STL】std::map使用小结
1、增
1)创建时,通过初始化的方式添加键值对:
#include <iostream>
#include <map>
#include <string>
void print_map(const std::map<std::string, int> &m)
{
for(const auto &a : m)
std::cout << a.first << " = " << a.second << ";" <<std::endl;
}
int main()
{
std::map<std::string, int> m{{"value1", 101}, {"value2", 102}, {"value3", 103}, {"value4", 104}};
print_map(m);
return 0;
}
输出
value1 = 101;
value2 = 102;
value3 = 103;
value4 = 104;
注意:在创建时,如果有“键”相同的,则会忽略后面的,比如改为:
std::map<std::string, int> m{{"value1", 101}, {"value1", 102}, {"value3", 103}, {"value3", 104}};
输出:
value1 = 101;
value3 = 103;
2)使用中括号“[]”,以数组形式插入,如果键存在会修改值
m["value2"] = 9527;
m["value3"] = 9528;
m["value5"] = 9529;
m["value6"] = 9530;
print_map(m);
输出
value1 = 101;
value2 = 9527;
value3 = 9528;
value4 = 104;
value5 = 9529;
value6 = 9530;
3)使用std::map::insert(std::pair<>())
使用方法如下,如果键已存在,不会修改值
m.insert(std::pair<std::string, int>("value7", 107));
m.insert(std::pair<std::string, int>("value4", 108));
4)使用std::map::insert(std::map<std::string, int>::value_type())
使用方法如下,如果键已存在,不会修改值
m.insert(std::map<std::string, int>::value_type("value8", 108));
m.insert(std::map<std::string, int>::value_type("value1", 999));
2、删
1)通过键值来删除:std::map::erase(key)
m.erase("value1");
m.erase("value2");
2)通过迭代器来删除:std::map::erase(iterator)
auto iter = m.begin();
iter++;
iter++;
m.erase(iter);
注意,当容器发生变化,比如执行了删除或者插入操作,迭代器将会失效,如果再使用将会崩溃。
C++没有检测迭代器是否失效的方法。
3)通过迭代器来删除一定范围内的所有项:std::map::erase(iterator begin, iterator end)
iter = m.begin();
iter++;
iter++;
m.erase(iter, m.end());
print_map(m);
4)删除所有项:std::map::clear()
m.clear();
3、改
只能修改值,不能直接修改键。如果要改键,只好先删除再添加
1)使用中括号“[]”,以数组形式来修改键对应的值,注意如果键不存在,将会插入到map中
m["value2"] = 95279527;
m["value3"] = 95289527;
2)使用非const迭代器来获取键值对,然后修改值
for(auto &a : m){
a.second = 888;
}
for(auto iter = m.begin(); iter != m.end(); iter++){
iter->second = 77777777;
}
4、查
1)std::map::find()
auto iter = m.find("value7");
std::cout << iter->first << " = " << iter->second << std::endl;
m.erase(iter);
print_map(m);
2)使用中括号“[]”,以数组来查找,当没有该键,将返回默认值,并且会插入到map中
std::cout << "value8 = " << m["value8"] << std::endl;
std::cout << "value unknow = " << m["unknow"] << std::endl;
3)std::map::at()
c++11引入的at方法,用于取值,但它是进行越界检测,这会损失效率。
如果存在,则返回它的值,如果不存在,则抛出异常:catch exception: invalid map<K, T> key
try
{
std::cout << "value8 = " << m["value8"] << std::endl;
std::cout << "value unknow = " << m["unknow"] << std::endl;
print_map(m); }
catch(std::exception& e)
{
std::cout << "catch exception: " << e.what() << std::endl;
}
try
{
std::cout << "value8 = " << m.at("value8") << std::endl;
std::cout << "value unknow1 = " << m.at("unknow1") << std::endl;
print_map(m); }
catch(std::exception& e)
{
std::cout << "catch exception: " << e.what() << std::endl;
//输出:catch exception: invalid map<K, T> key
}
std::cout << "value unknow2 = " << m.at("unknow2") << std::endl;
5、注意事项
5.1 值为指针时
如果std::map的值为指针时,再删除项前,需要先正确的释放指针,防止内存泄。
iter = m.begin();
while (iter != m.end())
{
delete iter->second;
iter->second = NULL;
iter = m.erase(iter);
}
5.2 删除迭代器
错误示例:
for ( map<int, string>::iterator it = str_map.begin(); it!=str_map.end(); it++ ) {
if ( some_condition )
str_map.erase(it);
}
erase(it)后,it这个迭代器将会失效,再次it++时会崩溃。
正确示例:
for ( map<int, string>::iterator it = str_map.begin(); it!=str_map.end(); ) {
if ( some_condition ) {
str_map.erase(it++);
} else {
it++;
}
}
str_map.erase(it++);先将it赋值给erase()的形参,这时it还没被删除,执行++,即it已迭代到下一个,然后erase()再执行,将形参中保存的、还没有迭代的项删除。
5.3 自定义std::map的key
自定义key需要满足以下两点:
- 自定义的类,需要重载运算符 <
- 如果没有“<”比较操作符,需要自定义第三个参数Compare,该仿函数实现“()”操作符,提供比较功能。插入时各节点顺序通过该仿函数来比较
std::map定义:
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
第一个key,第二个value,,第三个Compare是比较函数(小于),第四个是内存配置对象
std::map内部存储机制实际是以红黑树为基础,红黑树在插入节点时,必须依照大小比对之后在一个合适的位置上执行插入动作。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!