当std::map::at超出范围时返回什么

What to return when a std::map::at goes out_of_range?

本文关键字:范围 返回 什么 std map at      更新时间:2023-10-16

在游戏中,我希望搜索物品地图并返回位于棋盘特定方格上的物品。但是如果正方形是空的呢?(项目不存储在董事会结构中。为了这个问题的目的,不要介意那个。)我有下面的代码,但是我应该做什么来返回一个"空"引用?

map<pair<int, int>, Item*> _items;
Item& itemAt(int row, int col) const {
    try {  
        return *_items.at(make_pair(row, col));
    } catch(out_of_range& e) {
        return // what goes here?            
    } 
}

或者这是错误的方法,我应该使用find() ?

如果在程序中没有找到项不是错误条件,那么您应该不返回引用(因为引用不能为空)。相反,您应该返回一个(很可能是非拥有的)指针,并且在没有找到项目的情况下返回nullptr:

Item* itemAt(int row, int col) const {
    try {  
        return _items.at(make_pair(row, col));
    } catch(out_of_range& e) {
        return nullptr;
    }   
}

另一方面,如果找不到项是错误,那么你可以返回一个引用(当找到项时)并让异常传播当找不到项时-处理它的责任将属于你的代码中具有如何处理它的策略知识的部分:

Item& itemAt(int row, int col) const {
    return *_items.at(make_pair(row, col));
}

在这种情况下,使用指针作为表示" 0或1个对象"的手段是有用的:

Item* itemAt(int row, int col) const {
    try {
        return _items.at(make_pair(row, col));
    } catch(out_of_range& e) {
        return nullptr;
    }
}

然而,使用std::map::find()可能是一种更快更干净的方法。

如果客户端代码请求不存在的项目是错误的,那么throw将异常报告失败并返回Item&

如果不是错误,因为mapvalue_type已经是Item*,将返回类型更改为Node*并返回nullptr,以指示请求位置的项不存在,并使用map::find()

为了避免Item&返回类型已经存在的生命周期问题,可以考虑将value_type更改为std::shared_ptr<Item>。如果客户端代码有一个指向map值的引用或原始指针,并且从map中删除了该元素,那么客户端就留下了一个悬空指针/引用。切换到std::shared_ptr<Item>可以避免这种情况。itemAt()函数将返回一个std::shared_ptr<Item>。这还有一个好处,即map中的Item不需要显式地为delete d。

其实别人也有过同样的问题:

  • 有人写boost::optional
  • 你可以返回一对指针和返回值
  • 可以抛出异常
  • 你可以返回一个空对象