我对如何比较存储在集合中的对象有疑问。
class A
{
public:
char * name;
};
我在一个集合中存储A的对象。我提供了一个比较器类,它提供了operator()(A& ob1,A& ob2)的实现。在这里我比较ob1.name& ob2.name,当ob1.name小于ob2.name时返回true。
我能使用set的find()来搜索对象吗?我只为operator()提供了实现。这还够吗?有人可以解释一下find()在这种情况下是如何工作的吗?
提前致谢
答案 0 :(得分:4)
我能使用set的find()来搜索对象吗?我只为operator()提供了实现。这还够吗?
是的,只为comparator
课程提供仅operator ()(A&,A&)
的实施就足够了。请参阅默认比较器std::less<>
。
有人可以解释在这种情况下find()的工作原理吗?
非常简单的说法:std::set<T,comparator>::find(k)
当且仅当两个比较都失败时才返回迭代器it
:
否则返回std::set<>::end()
...
在数学意义上讲 - std::set
通过这个公式的弱排序来定义相等:
a == b <==> !(a < b) && !(b < a)
答案 1 :(得分:3)
将在std::set::find()
中使用的函数是您声明为集合的模板参数的Comparator
类的实例。
template < class Key, class Compare = less<Key>,
class Allocator = allocator<Key> > class set;
具体而言,比较器实例将传递给Key对象,如果第一个位于第二个对象之前,则应返回true。所以是的,您的实施很好。
现在,进一步挖掘:如果你想说服自己,你可以深入了解gcc标准库实现的源代码,你会发现:
template<typename _Key, typename _Val, typename _KeyOfValue,
typename _Compare, typename _Alloc>
typename _Rb_tree<_Key, _Val, _KeyOfValue,
_Compare, _Alloc>::iterator
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
find(const _Key& __k)
{
iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k);
return (__j == end()
|| _M_impl._M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j;
}
您可以看到_M_key_compare
(这是您提供的_Compare
班级的一个实例)被调用__k
作为第一个参数(您的Key
之一)和_S_key(...)
的返回值,这是一个关键。 _M_key_compare
的返回值用于三元表达式,因此它应该是一个布尔值。
答案 2 :(得分:2)
我在一个集合中存储A的对象。我提供了一个比较器类,它提供了operator()(A&amp; ob1,A&amp; ob2)的实现。
这是不正确的。容器std::set
根据在第二个模板参数中配置的比较器维护排序的元素。为了保证订单不变量不被破坏,容器将密钥存储为常量对象,这反过来意味着比较器必须按const &
取得密钥。
通常,比较器应该提供operator()
,它通过const-reference获取两个元素,而成员函数应该是const
本身:
struct comparator : std::binary_function<A,A,bool> {
bool operator()( A const& lhs, A const& rhs ) const;
};
答案 3 :(得分:1)
你可以使用set.find或set.count,如果找不到元素,set :: find()会返回set :: end(),如果找不到元素,则类似的计数为零。
set<Item*> itemSet;
Item* item = new Item();
if (itemSet.count(item) == 0)
{
std::cout<<"not found"
}
//or
if (itemSet.find(item) == itemSet.end())
{
std::cout<<"not found"
}