概述
map是STL里重要容器之一。它的特性总结来讲就是:所有元素都会根据元素的键值key自动排序(也可根据自定义的仿函数进行自定义排序),其中的每个元素都是<key, value>的键值对,map中不允许有键值相同的元素,因此map中元素的键值key不能修改,但是可以通过key修改与其对应的value。如果一定要修改与value对应的键值key,可将已存在的key删除掉,然后重新插入。cpp17 使用 extract
我们需要用键值对填充一个map
实例时,会碰到两种不同的情况:
- 键不存在。创建一个全新的键值对。
- 键已存在。修改键所对应的值。
我通常会使用insert
或emplace
函数对map
插入新元素,如果插入不成功,那么就是第二种情况,就需要去修改现有的元素。
insert
和emplace
都会创建一个新元素尝试插入到map
实例中,不过在第二种情况下,这个新生成的元素会被丢弃。(如果键已存在,无法通过insert 和 emplace 插入成功),两种情况下,我们都会多调用一次构造函数。try_emplace也无法插入成功,只是不再尝试创建新元素,不再调用一次构造函数
map的元素键是唯一的,因此插入操作将检查每个插入的元素是否具有与容器中已有元素相同的键,如果是,则不插入该元素,并将迭代器返回给此现有元素,如果函数返回一个值。
#include <iostream>
#include <map>
using namespace std;
int main()
{
cout << "---------------insert------------------"<<endl;
map<int,string> m2;
m2.insert({1,"111"});
m2.insert({2,"222"});
const auto [it1, success_1] = m2.insert({3,"333"});//pair insert ( const value_type& x ) | 在map中插入键值对x,注意x是一个键值对,返回值也是键值对
cout << "insert 333 res: " << success_1 << endl; // insert 333 res: 1
cout << (*it1).first << " " << (*it1).second << endl; //(*it1).first 3 , (*it1).second 333
插入成功返回插入元素迭代器, emplace同理
for (auto [k,v] : m2)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------------------------"<<endl;
const auto [it2, success_2] = m2.insert({3,"666"});
cout << "insert 666 res: " << success_2 << endl;// insert 666 res: 0
cout << (*it2).first << " " << (*it2).second << endl;// (*it2).first 3 , (*it2).second 333 插入失败返回当前元素迭代器,emplace同理
for (auto [k,v] : m2)
{
cout << "key: " << k << " value: " << v <<endl;
}
}
std::map
中的try_emplace
函数展开,这个函数是C++17添加的。下面是其函数声明之一:
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);
其函数第一个参数k
是插入的键,args
表示这个键对应的值。如果我们成功的插入了元素,那么函数就会返回一个迭代器,其指向新节点在表中的位置,组对中布尔变量的值被置为true。当插入不成功,组对中的布尔变量值会置为false,并且迭代器指向与新元素冲突的位置
Note:
std::map
中insert
和emplace
方法完全相同。try_emplace
与它们不同的地方在于,在遇到已经存在的键时,不会去构造组对。当相应对象的类型需要很大开销进行构造时,这对于程序性能是帮助的。
C++17中,添加了try_emplace
函数,其只有在满足条件的情况下,才能插入新元素。
#include <iostream>
#include <map>
using namespace std;
int main()
{
cout << "---------------emplace------------------"<<endl;
map<int,string> m1;
m1.emplace(1,"111");
m1.emplace(2,"222");
m1.emplace(3,"333");
for (auto [k,v] : m1)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------------------------"<<endl;
m1.emplace(3,"666");
for (auto [k,v] : m1)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------insert------------------"<<endl;
map<int,string> m2;
m2.insert({1,"111"});
m2.insert({2,"222"});
const auto [it1, success_1] = m2.insert({3,"333"});
cout << "insert 333 res: " << success_1 << endl;
for (auto [k,v] : m2)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------------------------"<<endl;
const auto [it2, success_2] = m2.insert({3,"666"});
cout << "insert 666 res: " << success_2 << endl;
for (auto [k,v] : m2)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------try_emplace------------------"<<endl;
map<int,string> m3;
m3.try_emplace(1,"111");
m3.try_emplace(2,"222");
const auto [it3, success_3] = m3.insert({3,"333"});
cout << "insert 333 res: " << success_1 << endl;
for (auto [k,v] : m3)
{
cout << "key: " << k << " value: " << v <<endl;
}
cout << "---------------------------------"<<endl;
const auto [it4, success_4] = m3.insert({3,"666"});
cout << "insert 666 res: " << success_2 << endl;
for (auto [k,v] : m3)
{
cout << "key: " << k << " value: " << v <<endl;
}
}
try_emplace
#include <iostream>
#include <utility>
#include <string>
#include <map>
auto print_node = [](const auto &node) {
std::cout << "[" << node.first << "] = " << node.second << 'n';
};
auto print_result = [](auto const &pair) {
std::cout << (pair.second ? "inserted: " : "ignored:
");
print_node(*pair.first);
};
int main()
{
using namespace std::literals;
std::map<std::string, std::string> m;
print_result( m.try_emplace("a", "a"s) );
print_result( m.try_emplace("b", "abcd") );
print_result( m.try_emplace("c", 10, 'c') );
print_result( m.try_emplace("c", "Won't be inserted") );
for (const auto &p : m) { print_node(p); }
}
There’s more…
如果我们将表的类型从std::map
换成std::unordered_map
,程序照样能工作。这样的话,当不同类型的表具有较好的性能特性时,我们就可以快速的进行切换。
最后
以上就是辛勤春天为你收集整理的try_emplace向std::map实例中高效并有条件的插入元素的全部内容,希望文章能够帮你解决try_emplace向std::map实例中高效并有条件的插入元素所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复