我尝试使用用户定义的结构体作为std::map中的键。为了做到这一点,我在结构中定义了比较运算符。然后我将类的两个示例添加到map中。
#include <map>
#include <iostream>
struct Fraction {
int num, den; // numerator and denumenator
explicit Fraction() : num(1), den(1) {}
explicit Fraction(int num_, int den_) : num(num_), den(den_) {}
bool operator<(const Fraction& rhs) const {
return num * rhs.den < den * rhs.num;
}
};
int main() {
std::map<Fraction, int> mymap;
mymap[Fraction(100, 100)] = 1;
mymap[Fraction(200, 200)] = 2;
std::cout << mymap.at(Fraction(100, 100)) << std::endl;
std::cout << mymap.at(Fraction(200, 200)) << std::endl;
}
我希望得到
1
2
但结果是
2
2
为什么?
1条答案
按热度按时间to94eoyn1#
如果
a < b
和b < a
都不为真,则map
认为两个 Keys 相等。第一个分数是
100/100
,第二个分数是200/200
,100/100 < 200/200
和200/200 < 100/100
在数学上都不正确。但是,您没有使用整数除法来进行比较,所以让我们检查num * rhs.den < den * rhs.num;
或100*200 < 200*100
,这也适用于那里。100*200 < 200*100
和200*100 < 100*200
都不为真,所以它们被认为是相等的。这就是为什么你在
mymap[Fraction(200, 200)] = 2;
中覆盖了mymap[Fraction(100, 100)] = 1;
存储的值,并且你的Map中只有一个 Key 分数。我注意到你在评论中说 “我在
operator<
中添加了额外的检查,以区分这两种情况”。这可能是一个错误,因为它会打破Fraction
类用户的期望。考虑以下代码片段:如果您修改了
operator<
,使其能够在map
中同时使用a
和b
作为 Keys,则两个 “should not happen” 情况中的一个将启动。备选方案:
std::multimap
,其中可以存储多个被视为相等的 * Key *。但是,这将更改您的Map,以便可以存储多个100/100
Keys,而不仅仅是100/100
和200/200
。std::map
: