加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – stl map operator []不好

发布时间:2020-12-16 03:44:37 所属栏目:百科 来源:网络整理
导读:我的代码审阅者已经指出,使用地图的operator []是非常糟糕的,导致错误: map[i] = new someClass; // potential dangling pointer when executed twice 要么 if (map[i]==NULL) ... // implicitly create the entry i in the map 虽然我在阅读API后看到inser
我的代码审阅者已经指出,使用地图的operator []是非常糟糕的,导致错误:
map[i] = new someClass;    // potential dangling pointer when executed twice

要么

if (map[i]==NULL) ...      // implicitly create the entry i in the map

虽然我在阅读API后看到insert()更好的风险,因为它检查重复,因此可以避免悬挂指针发生,我不明白如果处理正确,为什么[]不能用于所有?

我选择地图作为我的内部容器,正是因为我想使用其快速和自我解释的索引功能.

我希望有人可以和我争辩更多,或站在我身边:)

解决方法

当你想要设置一个键的值(如果已经有一个值覆盖它),那么operator []可以使用的唯一时间(我可以想到),而且你知道覆盖是安全的它应该是因为你应该使用智能指针,而不是原始指针),并且是廉价的默认构造,在某些上下文中,该值应该具有无投掷构造和赋值.

例如(类似于你的第一个例子)

std::map<int,std::unique_ptr<int>> m;
m[3] = std::unique_ptr<int>(new int(5));
m[3] = std::unique_ptr<int>(new int(3)); // No,it should be 3.

否则有几种方法可以根据上下文来做,但是我建议总是使用一般的解决方案(这样你就不能错了).

找到一个值并创建它,如果它不存在:

一般解决方案(推荐,因为它一直有效)

std::map<int,std::unique_ptr<int>> m;
auto it = m.lower_bound(3);
if(it == std::end(m) || m.key_comp()(3,it->first))
   it = m.insert(it,std::make_pair(3,std::unique_ptr<int>(new int(3)));

2.价廉物美价廉

std::map<int,std::unique_ptr<int>> m;
auto& obj = m[3]; // value is default constructed if it doesn't exists.
if(!obj)
{
   try
   {
      obj = std::unique_ptr<int>(new int(3)); // default constructed value is overwritten.
   }
   catch(...)
   {
      m.erase(3);
      throw;
   }
}

3.以廉价的违约建筑和无投注价值

std::map<int,my_objecct> m;
auto& obj = m[3]; // value is default constructed if it doesn't exists.
if(!obj)
   obj = my_objecct(3);

注意:您可以轻松地将一般解决方案包含在帮助程序中:

template<typename T,typename F>
typename T::iterator find_or_create(T& m,const typename T::key_type& key,const F& factory)
{
    auto it = m.lower_bound(key);
    if(it == std::end(m) || m.key_comp()(key,it->first))
       it = m.insert(it,std::make_pair(key,factory()));
    return it;
}

int main()
{
   std::map<int,std::unique_ptr<int>> m;
   auto it = find_or_create(m,3,[]
   {
        return std::unique_ptr<int>(new int(3));
   });
   return 0;
}

注意,我传递一个模板化的工厂方法,而不是一个创建大小写的值,这样,当找到该值并且不需要创建时,就没有开销.由于lambda作为模板参数传递,编译器可以选择内联它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读