C++ 在STL映射中,使用map::insert比使用[]更好吗?

C++ 在STL映射中,使用map::insert比使用[]更好吗?,c++,dictionary,stl,insert,stdmap,C++,Dictionary,Stl,Insert,Stdmap,不久前,我和一位同事讨论了如何在STL中插入值。我更喜欢map[key]=值因为它感觉很自然,读起来很清晰,而他更喜欢map.insert(std::make_pair(key,value)) 我刚问过他,我们都不记得为什么insert更好,但我相信这不仅仅是一种风格偏好,还有一个技术原因,比如效率。简单地说:“严格地说,这个成员函数是不必要的:它的存在只是为了方便。” 有人能告诉我这个原因吗,或者我只是在梦想有一个原因?当涉及到地图中已经存在的关键点时,这两个原因有不同的语义。因此,它们并不具

不久前,我和一位同事讨论了如何在STL中插入值。我更喜欢
map[key]=值因为它感觉很自然,读起来很清晰,而他更喜欢map.insert(std::make_pair(key,value))

我刚问过他,我们都不记得为什么insert更好,但我相信这不仅仅是一种风格偏好,还有一个技术原因,比如效率。简单地说:“严格地说,这个成员函数是不必要的:它的存在只是为了方便。”


有人能告诉我这个原因吗,或者我只是在梦想有一个原因?

当涉及到地图中已经存在的关键点时,这两个原因有不同的语义。因此,它们并不具有直接可比性


但是操作符[]版本要求默认构造值,然后赋值,因此如果这比复制构造更昂贵,那么它将更昂贵。有时默认构造没有意义,那么就不可能使用运算符[]版本。

如果默认构造函数的性能影响不是问题,那么请选择可读性更好的版本

:)

当你写作时

map[key] = value;
无法判断您是替换了
键的
,还是
值创建了一个新的

将只创建:

using std::cout; using std::endl;
typedef std::map<int, std::string> MyMap;
MyMap map;
// ...
std::pair<MyMap::iterator, bool> res = map.insert(MyMap::value_type(key,value));
if ( ! res.second ) {
    cout << "key " <<  key << " already exists "
         << " with value " << (res.first)->second << endl;
} else {
    cout << "created key " << key << " with value " << value << endl;
}
使用std::cout;使用std::endl;
typedef std::map MyMap;
我的地图;
// ...
std::pair res=map.insert(MyMap::value_type(key,value));
如果(!res.second){

CUTH.P>一个带有map的::插入()是,如果在映射中已经存在键,它将不能替换一个值。我看到Java程序员编写的C++代码,它们期望的插入()在java中的行为与java中的值相同。
使用名称空间std;
使用命名空间boost::assign;//将“map\u list\u of()”引入范围
使某物无效
{
map my_map=map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);
}

另一件要注意的事情是
std::map

myMap[nonExistingKey];
将在映射中创建一个新条目,并将其键入到
nonExistingKey
初始化为默认值


当我第一次看到它时(当我的头撞上一个臭名昭著的遗留错误时),这把我吓坏了。我没想到会这样。对我来说,这看起来像是一个get操作,我也没想到会有“副作用”。首选
map.find()
从地图获取信息。

这是一个相当有限的案例,但从我收到的评论来看,我认为值得注意

我以前见过人们以地图的形式使用地图

map< const key, const val> Map;
mapmap;
要避免意外值覆盖的情况,请继续写入其他一些代码位:

const_cast< T >Map[]=val;
const_castMap[]=val;
我记得他们这样做的原因是因为他们确信在这些特定的代码位中,他们不会覆盖映射值;因此,继续使用更“可读”的方法
[]

实际上,我从来没有因为这些人编写的代码而遇到过任何直接的麻烦,但直到今天,我仍然强烈地感觉到,风险——无论多么小——都不应该在容易避免的情况下承担


在处理绝对不能覆盖的映射值时,请使用
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 ) ;

}
void映射测试()
{
地图m;
for(int i=0;i first,result.first->second);
其他的
printf(“!映射已经包含%d=>值%f,没有更改\n”,result.first->first,result.first->second);
}
放置(“所有映射值:”);
for(map::iterator iter=m.begin();iter!=m.end();++iter)
printf(“%d=>%f\n”,iter->first,iter->second);
///现在看这个。。
m[5]=900.f;//使用运算符[]覆盖映射值
放置(“所有映射值:”);
for(map::iterator iter=m.begin();iter!=m.end();++iter)
printf(“%d=>%f\n”,iter->first,iter->second);
}

如果您的应用程序是速度关键型的,我建议使用[]操作符,因为它总共创建了原始对象的3个副本,其中2个是临时对象,并且迟早会被销毁

但在insert()中,创建了原始对象的4个副本,其中3个是临时对象(不一定是“临时对象”),并被销毁

这意味着额外的时间: 1.一个对象内存分配 2.一个额外的构造函数调用 3.一个额外的析构函数调用 4.一个对象内存释放

如果您的对象很大,构造函数是典型的,析构函数会释放大量资源,以上几点更重要。关于可读性,我认为两者都是公平的

同样的问题出现在我的脑海中,但不是可读性太强,而是速度太快。 下面是一个示例代码,通过它我了解了我提到的要点

class Sample
{
    static int _noOfObjects;

    int _objectNo;
public:
    Sample() :
        _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside default constructor of object "<<_objectNo<<std::endl;
    }

    Sample( const Sample& sample) :
    _objectNo( _noOfObjects++ )
    {
        std::cout<<"Inside copy constructor of object "<<_objectNo<<std::endl;
    }

    ~Sample()
    {
        std::cout<<"Destroying object "<<_objectNo<<std::endl;
    }
};
int Sample::_noOfObjects = 0;


int main(int argc, char* argv[])
{
    Sample sample;
    std::map<int,Sample> map;

    map.insert( std::make_pair<int,Sample>( 1, sample) );
    //map[1] = sample;
    return 0;
}
类示例
{
静态整数对象;
int_objectNo;
公众:
示例():
_objectNo(_noOfObjects++)
{

现在在c++11中,我认为在STL映射中插入一对的最好方法是:

typedef std::map<int, std::string> MyMap;
MyMap map;

auto& result = map.emplace(3,"Hello");
typedef std::map MyMap;
我的地图;
auto&result=map.emplace(3,“你好”);
结果将是一对:

  • 第一个元素(result.First)指向插入的对或指向 如果密钥已存在,则与该密钥配对

  • 第二个元素(result.Second),如果插入正确或 错了,出了什么事

附言:如果你没有关于t的案例
typedef std::map<int, std::string> MyMap;
MyMap map;

auto& result = map.emplace(3,"Hello");
string word;
map<string, size_t> dict;
while(getline(cin, word)) {
    dict.insert(make_pair(word, dict.size()));
}
string word;
map<string, size_t> dict;
while(getline(cin, word)) {
    size_t sz = dict.size();
    if (!dict.count(word))
        dict[word] = sz; 
}