前段时间,我和同事讨论了如何在STL映射中插入值。I prefer map[key] = value;因为它让人感觉自然,读起来清晰,而他更喜欢地图。插入(std:: make_pair(关键字,值))。
我只是问了他,我们都不记得为什么插入更好,但我相信这不仅仅是一个风格偏好,而是有一个技术原因,如效率。SGI STL引用简单地说:“严格地说,这个成员函数是不必要的:它只是为了方便而存在。”
有人能告诉我原因吗,还是我只是在做梦?
前段时间,我和同事讨论了如何在STL映射中插入值。I prefer map[key] = value;因为它让人感觉自然,读起来清晰,而他更喜欢地图。插入(std:: make_pair(关键字,值))。
我只是问了他,我们都不记得为什么插入更好,但我相信这不仅仅是一个风格偏好,而是有一个技术原因,如效率。SGI STL引用简单地说:“严格地说,这个成员函数是不必要的:它只是为了方便而存在。”
有人能告诉我原因吗,还是我只是在做梦?
当前回答
当涉及到映射中已经存在的键时,两者具有不同的语义。所以它们没有直接的可比性。
但是操作符[]版本需要默认构造值,然后赋值,所以如果这比复制构造更昂贵,那么它也会更昂贵。有时默认结构没有意义,那么就不可能使用操作符[]版本。
其他回答
当涉及到映射中已经存在的键时,两者具有不同的语义。所以它们没有直接的可比性。
但是操作符[]版本需要默认构造值,然后赋值,所以如果这比复制构造更昂贵,那么它也会更昂贵。有时默认结构没有意义,那么就不可能使用操作符[]版本。
这是一个相当有限的情况,但从我收到的评论来看,我认为这是值得注意的。
我以前见过有人用地图的形式
map< const key, const val> Map;
为了避免意外重写值的情况,然后继续写一些其他的代码:
const_cast< T >Map[]=val;
我记得他们这么做的原因是因为他们确信在这些特定的代码中他们不会覆盖map值;因此,继续使用更“可读”的方法[]。
实际上,我从来没有因为这些人写的代码而遇到过任何直接的麻烦,但直到今天,我仍然强烈地感觉到,当风险可以轻松避免时,不应该冒任何风险——无论风险有多小。
在处理绝对不能重写的映射值的情况下,请使用insert。不要仅仅为了可读性而破例。
insert()和operator[]之间的区别已经在其他答案中很好地解释了。然而,c++ 11和c++ 17分别引入了新的std::map插入方法:
c++ 11提供了emplace(),在einpoklum的评论和GutiMac的回答中也提到过。 c++ 17提供了insert_or_assign()和try_emplace()。
让我简单总结一下“新”插入方法:
emplace(): When used correctly, this method can avoid unnecessary copy or move operations by constructing the element to be inserted in place. Similar to insert(), an element is only inserted if there is no element with the same key in the container. insert_or_assign(): This method is an "improved" version of operator[]. Unlike operator[], insert_or_assign() doesn't require the map's value type to be default constructible. This overcomes the disadvantage mentioned e.g. in Greg Rogers' answer. try_emplace(): This method is an "improved" version of emplace(). Unlike emplace(), try_emplace() doesn't modify its arguments (due to move operations) if insertion fails due to a key already existing in the map.
有关insert_or_assign()和try_emplace()的更多详细信息,请在这里看到我的回答。
Coliru上的简单示例代码
需要注意的是,您也可以使用Boost。分配:
using namespace std;
using namespace boost::assign; // bring 'map_list_of()' into scope
void something()
{
map<int,int> my_map = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);
}
现在在c++11中,我认为在STL映射中插入一对的最好方法是:
typedef std::map<int, std::string> MyMap;
MyMap map;
auto& result = map.emplace(3,"Hello");
结果将是一对:
第一个元素(result.first),指向插入或指向的对 如果密钥已经存在,则使用此密钥对。 第二个元素(result.second),如果插入正确则为true 假装出了什么差错。
PS:如果你不关心顺序,你可以使用std::unordered_map;)
谢谢!