C++ C++;98 std::map::at()的包装器
我只能使用C++98,无法访问随C++11添加的C++ C++;98 std::map::at()的包装器,c++,c++11,stl,C++,C++11,Stl,我只能使用C++98,无法访问随C++11添加的std::map::at()的实现 我的目标是编写一个非成员函数at()函数(使用C++98),其行为类似于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_r
std::map::at()
的实现
我的目标是编写一个非成员函数at()
函数(使用C++98),其行为类似于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;
}
模板
V&at(标准::地图,K键)
{
if(map.find(key)=map.end())
抛出标准::超出范围(“未找到键”);
返回map.find(key)->second;
}
我至少可以看到一个问题,那就是我的版本的行为就像我返回了一个副本一样(见下文)
std::map myMap;
myMap.insert(std::pair(2,43));
//myMap.at(2)=44;//修改引用
//断言(44==myMap.at(2));//好的
at(myMap,2)=44;//不修改地图内的值,为什么?
断言(44==myMap.at(2));//不好
将签名更改为
V& at(std::map<K, V>& map, K key)
V&at(标准::地图和地图,K键)
主要问题是您正在调用未定义的行为
您的at
按值获取地图:
V& at(std::map<K, V> map, K key)
V&at(标准::地图,K键)
因此,您将返回对本地对象中某个项的引用,这是非常未定义的
您应该使用参考:
V& at(std::map<K, V>& map, const K& key)
V&at(标准::映射与映射、常数K与键)
您可能还想添加常量版本:
const V& at(const std::map<K, V>& map, const K& key)
const V&at(const std::map&map,const K&key)
您的方法存在两个问题:
- 您将映射实例作为值传递,这样不仅可以复制整个映射,还可以返回对该本地副本中某个元素的引用并生成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;
}
模板
V&at(标准::地图和地图,K键)
{
std::map::迭代器f=map.find(键);
如果(f==map.end())
抛出标准::超出范围(“未找到键”);
返回f->second;
}
您应该将find
的结果存储在一个变量中,这样就不会遍历地图两次。这个问题似乎离题了,因为它是关于什么是打字错误。@KubaOber我不同意。问题更多的是,我们不理解为什么按值传递映射
比简单的打字更不能修改元素。OP显然不明白为什么按值传递它不能像他期望的那样工作。假设您的密钥都可以打印,您也可以通过说明找不到哪个密钥来增强错误消息。可能会帮助您在以后抛出此错误时找到错误。
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;
}