【STL】std::map使用小结

1、增

1)创建时,通过初始化的方式添加键值对:

#include 
#include 
#include 

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 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::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 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 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 Alloc = alloc>

第一个key,第二个value,,第三个Compare是比较函数(小于),第四个是内存配置对象
std::map内部存储机制实际是以红黑树为基础,红黑树在插入节点时,必须依照大小比对之后在一个合适的位置上执行插入动作。

你可能感兴趣的:(C++,c++)