前段时间,我和同事讨论了如何在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不会覆盖键值。

void mapTest()
{
  map<int,float> m;


  for( int i = 0 ; i  <=  2 ; i++ )
  {
    pair<map<int,float>::iterator,bool> result = m.insert( make_pair( 5, (float)i ) ) ;

    if( result.second )
      printf( "%d=>value %f successfully inserted as brand new value\n", result.first->first, result.first->second ) ;
    else
      printf( "! The map already contained %d=>value %f, nothing changed\n", result.first->first, result.first->second ) ;
  }

  puts( "All map values:" ) ;
  for( map<int,float>::iterator iter = m.begin() ; iter !=m.end() ; ++iter )
    printf( "%d=>%f\n", iter->first, iter->second ) ;

  /// now watch this.. 
  m[5]=900.f ; //using operator[] OVERWRITES map values
  puts( "All map values:" ) ;
  for( map<int,float>::iterator iter = m.begin() ; iter !=m.end() ; ++iter )
    printf( "%d=>%f\n", iter->first, iter->second ) ;

}

事实上,std::map insert()函数不会覆盖与键相关的值,这允许我们像这样编写对象枚举代码:

string word;
map<string, size_t> dict;
while(getline(cin, word)) {
    dict.insert(make_pair(word, dict.size()));
}

当我们需要将不同的非唯一对象映射到范围0..N的某个id时,这是一个非常常见的问题。这些id可以稍后使用,例如,在图算法中。在我看来,使用操作符[]的替代选项看起来可读性较差:

string word;
map<string, size_t> dict;
while(getline(cin, word)) {
    size_t sz = dict.size();
    if (!dict.count(word))
        dict[word] = sz; 
} 

需要注意的是,您也可以使用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;)

谢谢!