当键不存在时,对象的C++映射将被擦除

C++ map of objects erase when key not present

本文关键字:映射 C++ 擦除 对象 不存在      更新时间:2023-10-16

我在C++(gcc)中有以下映射:

map<int, EdgeExtended> myMap;

其中EdgeExtended的定义为:

struct EdgeExtended {
    int neighborNodeId;
    int weight;
    int arrayPointer;
    bool isCrossEdge;
    EdgeExtended(Edge _edge, int _arrayPointer) {
        neighborNodeId = _edge.neighborNodeId;
        weight = _edge.weight;
        arrayPointer = arrayPointer;
        isCrossEdge = _edge.isCrossEdge;
    }
    EdgeExtended(const EdgeExtended & _edge) {
        neighborNodeId = _edge.neighborNodeId;
        weight = _edge.weight;
        arrayPointer = _edge.arrayPointer;
        isCrossEdge = _edge.isCrossEdge;
    }
    EdgeExtended(int _neighborNodeId, int _weight, bool _isCrossEdge, int _arrayPointer) {
        neighborNodeId = _neighborNodeId;
        weight = _weight;
        arrayPointer = _arrayPointer;
        isCrossEdge = _isCrossEdge;
    }
    void setValues(int _neighborNodeId, int _weight, bool _isCrossEdge, int _arrayPointer) {
        neighborNodeId = _neighborNodeId;
        weight = _weight;
        arrayPointer = _arrayPointer;
        isCrossEdge = _isCrossEdge;
    }
    EdgeExtended() {
        neighborNodeId = -1;
        weight = -1;
        arrayPointer = -1;
        isCrossEdge = false;
    }
};

我想这样做(简单的例子):

EdgeMap edge;
int nodeId=18;
edge=map.erase(nodeId);

a) 这个代码正确吗,擦除返回键对应的对象吗?b) 如果是,当密钥不存在时,擦除返回什么?c) 如果这个代码是错误的,我如何检查是否存在密钥、映射到该密钥的对象,然后从映射中删除该对。请记住,性能是至关重要的,所以我需要最有效的方法。

a)不,这是不正确的。您调用的std::map::erase方法返回已擦除元素的数量。

您可以使用std::map::find来检查具有给定键的元素是否在映射中。如果元素存在,则返回迭代器;如果不存在,则向end()返回。您可以将此迭代器传递给相关的std::map::erase重载。

EdgeMap edge;
int nodeId=18;
ExtendedEdge removedEdge;
....
EdgeMap::iterator it = edge.find(nodeId);
if( it != edge.end() ) 
{
  // found element.
  removedEdge = it->second; // or removeEdge = std::move(it->second) in C++11
  edge.erase(it);
}

a) 此代码是否正确,是否擦除返回对应的对象钥匙?

否,这将返回已删除的元素数。

b) 如果是,当密钥不存在时,擦除返回什么?

不适用。它只是简单地返回0

c) 如果这个代码是错误的,我如何检查是否存在密钥对象映射到密钥,然后从映射中删除该对。(使)留在家里请注意,性能相当关键,所以我需要最高效的方法

auto it = yourMap.find(nodeId);
if (it != yourMap.end()) {
   EdgeExtended theObjectToRemove = *it;
   yourMap.erase(it);
}

这与普通erase(nodeId);的复杂性相同,因为erase(it)需要分摊的恒定时间。

我会用迭代器来完成,比如:

typedef map<int, EdgeExtended> EdgeMap;
bool RemoveEdge( EdgeMap & myMap, int nodeId, EdgeExtended &edge )
{
    EdgeMap::iterator e = myMap.find(nodeId);
    if( e == myMap.end() ) return false;
    edge = e->second;
    myMap.erase(e);
    return true;
}