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

相关推荐

  1. Dynamo 使用小结

    2023-12-31 01:34:05       49 阅读
  2. flink-cdc使用小结

    2023-12-31 01:34:05       52 阅读
  3. HCSC单片机使用小结

    2023-12-31 01:34:05       41 阅读
  4. GIT使用小结

    2023-12-31 01:34:05       38 阅读
  5. 【STL】std::map使用小结

    2023-12-31 01:34:05       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-31 01:34:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-31 01:34:05       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-31 01:34:05       82 阅读
  4. Python语言-面向对象

    2023-12-31 01:34:05       91 阅读

热门阅读

  1. TypeScript 类方法装饰器

    2023-12-31 01:34:05       59 阅读
  2. 什么是redis雪崩

    2023-12-31 01:34:05       56 阅读
  3. ELF Strip

    2023-12-31 01:34:05       43 阅读
  4. RabbitMQ消息队列常见面试题

    2023-12-31 01:34:05       56 阅读
  5. Git 命令

    2023-12-31 01:34:05       44 阅读
  6. 【Linux】修复 Linux 错误 - 地址已在使用中

    2023-12-31 01:34:05       51 阅读
  7. ❀My排序算法学习之选择排序❀

    2023-12-31 01:34:05       53 阅读
  8. CAPL解析DBC文件

    2023-12-31 01:34:05       68 阅读
  9. OpenFeign相关面试题及答案

    2023-12-31 01:34:05       43 阅读
  10. linux安装nginx

    2023-12-31 01:34:05       48 阅读
  11. asset模块在Github的含义

    2023-12-31 01:34:05       56 阅读
  12. 离线服务器中python包的安装

    2023-12-31 01:34:05       50 阅读
  13. webscoket多个客户端同时向一个服务器传输数据

    2023-12-31 01:34:05       58 阅读