【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内部存储机制实际是以红黑树为基础,红黑树在插入节点时,必须依照大小比对之后在一个合适的位置上执行插入动作。

  • 22
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭老二

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值