由于std::map中,元素的key是唯一的,我们经常遇到这样的场景,向map中插入元素时,先检测map指定的key是否存在,不存在时才做插入操作,如果存在,直接取出来使用,或者key不存在时,做插入操作,存在时做更新操作。
通用的做法,可以直接用emplace操作,判断指定的key是否存在,如果不存在,则插入元素,当元素存在的时候,emplace依然会构造一次带待插入元素,判断不需要插入后,将该元素析构,这样导致的后果是,产生了多余的构造和析构操作。
鉴于此,C++17引入了std::try_emplace,在参数列表中,把key和value分开,该方法会检测指定的key是否存在,如果存在,什么也不做,不存在,则插入相应的value。
此外,C++17为map容器还新增了insert_or_assign方法,让我们无需像之前一样,额外编写先判断是否存在,不存在则插入,存在则更新的代码了。
废话不多说,看简单的demo实例代码:
using namespace std;
void PrintMap(const string& type, const map<string, int>& val)
{
cout << type << endl;
for (const auto& [user, age] : val)
{
cout << user << ":" << age << endl;
}
}
int main()
{
map<string, int> map_user_age = { {"Tom", 10}, {"Jerry", 12}, {"Neo", 13} };
PrintMap("original map", map_user_age);
auto [iter_tom, inserted_tom] = map_user_age.try_emplace("Tom", 14);
PrintMap("insert Tom:14(try_emplace)", map_user_age);
auto [iter_jim, inserted_jim] = map_user_age.try_emplace("Jim", 14);
PrintMap("insert Jim:14(try_emplace)", map_user_age);
auto [iter_neo, inserted_neo] = map_user_age.insert_or_assign("Neo", 18);
PrintMap("insert Neo:18(insert_or_assign)", map_user_age);
auto [iter_tom_ia, inserted_tom_ia] = map_user_age.insert_or_assign("Tom", 16);
PrintMap("insert Tom:16(insert_or_assign)", map_user_age);
return 0;
}
猜一猜运行结果:
上述实例代码可以看到:insert_or_assign方法与 try_emplace的不同之处在于,如果对应的key已经存在,使用insert_or_assign会将新的value值赋值给已经存在的key(建立新的键值对映射)。