繁体   English   中英

用于std :: map :: at()的C ++ 98 Wrapper

[英]C++98 Wrapper for std::map::at()

我只能使用C ++ 98,并且无法访问随C ++ 11添加的std::map::at()实现。

我的目标是at()函数(使用C ++ 98)上编写非成员函数at()其行为类似于std::map::at()

因此我写了以下非成员函数:

template<typename K, typename V>
V& at(std::map<K, V> map, K key)
{
  if (map.find(key) == map.end())
    throw std::out_of_range("key not found");
  return map.find(key)->second;
}

我至少可以看到一个问题,就是我的版本表现得好像我已经返回了一个副本(见下文)。

std::map<int,int> myMap;
myMap.insert(std::pair<int,int>(2,43));

// myMap.at(2)=44;            // modifies the reference
// assert(44==myMap.at(2));   // fine 

at(myMap,2)=44;               // does not modify the value inside the map, why?
assert(44==myMap.at(2));      // not fine
  1. 我该如何解决这个问题?
  2. 我的包装器还有其他问题吗?

主要问题是您正在调用未定义的行为。

您的at按地图获取地图:

V& at(std::map<K, V> map, K key)

所以你要返回一个对本地对象中的项的引用,这是非常未定义的。

你应该使用一个参考:

V& at(std::map<K, V>& map, const K& key)

您可能还想添加const版本:

const V& at(const std::map<K, V>& map, const K& key)

将签名更改为

V& at(std::map<K, V>& map, K key)

你的方法中有2个问题:

  • 您将地图实例作为值传递,这样不仅可以复制整个地图,还可以返回对该本地副本中的元素的引用并生成UB
  • 你做了两次查找,这在地图上是相当昂贵的操作

所以你的代码可能是:

template<typename K, typename V>
V& at(std::map<K, V> &map, K key)
{
   std::map<K,V>::iterator f = map.find(key);
   if ( f == map.end())
     throw std::out_of_range("key not found");
   return f->second;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM