std::map 擦除错误的元素

std::map erase wrong element

当我尝试擦除我的地图的元素时,似乎是另一个元素被擦除。 我认为这是对 operator< 的错误覆盖,但我没有看到问题。

inline bool operator<(const Etat &et){
    if (et.x < this->x){
        return false;
    }
    else if (et.x > this->x){
        return true;
    }
    if (et.y < this->y){
        return false;
    }
    else if (et.y > this->y){
        return true;
    }
    if (et.ry < this->ry){
        return false;
    }
    else if (et.ry > this->ry){
        return true;
    }
};

Etat 构造函数:

Etat(x, y, ry, useless, useless);

和地图:

std::map< Etat, double > map;
//The 2 last parameters of Etat are useless
map.insert(std::pair< Etat, double >(Etat(2, 2, 2, 0, 0), 0.0));
//map.size() = 1
Etat e (0, 5 ,3, 0, 0);
map.erase(e);
//map.size() = 0
//Etat(2, 2, 2) is gone

我没有遇到地图中所有 Etat 实例的问题,只是这个案例和其他一些案例。

在家测试一下:

#ifndef Etat_H
#define Etat_H

#include<iostream>

class Etat
{
public:
Etat(const int x, const int y, const int ry, const double vx, const double vy)
{
    this->x = x;
    this->y = y;
    this->ry = ry;
    this->vx = vx;
    this->vy = vy;
};

Etat(){};
inline bool operator==(const Etat& et){
    if (et.x == this->x && et.y == this->y && et.ry == this->ry && et.vx == this->vx && et.vy == this->vy){
        return true;
    }
    return false;
};
inline bool operator!=(const Etat& et){
    if (*this == et){
        return false;
    }
    return true;
};
inline bool operator<(const Etat &et){
    if (et.x < this->x){
        return false;
    }
    else if (et.x > this->x){
        return true;
    }
    if (et.y < this->y){
        return false;
    }
    else if (et.y > this->y){
        return true;
    }
    if (et.ry < this->ry){
        return false;
    }
    else if (et.ry > this->ry){
        return true;
    }
};

inline bool operator>(const Etat& et){
    if (*this < et){
        return false;
    }
    return true;
};

inline const int getX() const {
    return this->x;
};

inline const int getY() const {
    return this->y;
};

inline const int getRY() const {
    return this->ry;
};

private:
    int x, y;
    int ry;
    double vx, vy;
};

#endif // !Etat_H

一小段代码可以重现问题:

std::map< Etat, double > map;
map.insert(std::pair< Etat, double >(Etat(2, 2, 2, 0, 0), 0.0));
Etat e (0, 5 ,3, 0, 0);
map.erase(e);

要将您的 class 用作地图中的键,您必须定义元素何时相等。所以定义比较器 class:

struct EtatCompare {
   bool operator() (const Etat& e1, const Etat& e2) const {
       return e1.x != e2.x || e1.y != e2.y || e1.ry != e2.ry || e1.vx != e2.vx || e1.vy != e2.vy; //TODO: fill all the needed conditions here
   }
};

并使用它创建地图:

std::map< Etat, double, EtatCompare > map;

你少了一个

else {
    throw "no matching if"; // alternatively return either true or false.
}

您的编译器应该给出警告,指出存在没有 return.

的情况

并非您的 operator< return 值的所有路径。具体来说,当et == *this.

如果您使用的是 C++11 或更高版本,请改用 std::tie()

inline bool operator<(const Etat &rhs) const
{
    return std::tie(x, y, ry) < std::tie(rhs.x, rhs.y, rhs.ry);
}

您可以为 operator==operator> 实施做同样的事情:

bool operator==(const Etat &rhs) const
{
    return std::tie(x, y, ry) == std::tie(rhs.x, rhs.y, rhs.ry);
}

bool operator>(const Etat &rhs) const
{
    return std::tie(x, y, ry) > std::tie(rhs.x, rhs.y, rhs.ry);
}