c++中std::map中的compare函数如果自反为真,该如何工作?
How does the compare function in std::map in C++ work if it is reflexively true?
我有一个地图在我的项目。每次插入新元素时,我都希望确保所插入的新元素的键至少与映射中的其他元素有最小的距离。为此,我编写了一个自定义比较类,如下所示:
class PulseCompare
{
public:
PulseCompare(int minwidth_):minwidth(minwidth_){};
bool operator()(const int x, const int y) const {
if(abs(x-y)>minwidth) return false;
else return true;
}
private:
int minwidth;
};
并创建如下的映射:
std::map<int,float,PulseCompare> pulsemap(PulseCompare(256));
在我插入一个元素之前,我使用map.find
方法,像这样:
if ( pulsemap.find(1600) == pulsemap.end() ) {
// not found so I can insert
} else {
// found
}
但问题是,当map试图使用上述比较函数通过交换x
和y
的值进行反射性比较时,它将得到两个情况下的true
,而<
和>
等正常比较操作符通常不会出现这种情况
在std::map::key_comp
的cplusplus文档页面上,这里说,我引用
map对象的比较对象在构造时设置。它的类型(成员key_compare)是映射模板的第三个模板形参。默认情况下,这是一个less对象,返回与操作符"<"相同的结果。
该对象决定容器中元素的顺序:它是一个函数指针或接受与元素键相同类型的两个实参的函数对象,如果按照其定义的严格弱顺序认为第一个实参在第二个实参之前,则返回true,否则返回false。
如果key_comp自反性地返回false(即,无论键作为参数传递的顺序如何),则认为两个键是等价的。
但这并没有说明它是自反性的true
的情况。有谁能告诉我它到时候会是什么样子吗?或者我应该只通过遍历整个映射来进行区间比较?
-
std::map
中使用的比较器必须提供对象的严格弱排序。 - 您的比较器没有。
- 因此,你的
std::map
实例将产生未定义的行为。
注意:通常让比较器提供总排序更容易。
另外,让我们描述严格弱排序需要什么。这里,我摘自c++ 2011,第25.4节。
- 你将创建一个函子
Compator comp;
,我将把comp(lhs, rhs)
称为返回布尔值的函数。把它想象成lhs < rhs
是有帮助的。 - 我们将创建一个函数
equiv(lhs, rhs)
。这被定义为(!comp(lhs, rhs) && !comp(rhs, lhs))
。所以,!(lhs < rhs) && !(rhs < lhs)
.
我们需要遵守以下规则:
comp(a, b) && comp(b, c) implies comp(a, c)
equiv(a, b) && equiv(b, c) implies equiv(a, c)
为什么不直接使用它作为比较器呢?
return minwidth < (y - x);
下面是一个工作示例:http://coliru.stacked-crooked.com/a/e115d3a2f6714773
实际上,如果您这样重写比较器,它应该可以工作:
bool operator()(const int x, const int y) const {
if(abs(x-y)<=minwidth) return false;
else return x < y;
}
你不需要在插入之前使用find,你在做双重工作。只要尝试插入,如果这样的键存在,map将拒绝插入。std::map::insert
还返回std::pair<iterator,bool>
,因此您可以检查插入是否成功。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?