find()用于std :: set

时间:2012-09-28 23:18:21

标签: c++ stl set std

我对如何比较存储在集合中的对象有疑问。

class A
{
public:  
char * name;
};

我在一个集合中存储A的对象。我提供了一个比较器类,它提供了operator()(A& ob1,A& ob2)的实现。在这里我比较ob1.name& ob2.name,当ob1.name小于ob2.name时返回true。

我能使用set的find()来搜索对象吗?我只为operator()提供了实现。这还够吗?有人可以解释一下find()在这种情况下是如何工作的吗?

提前致谢

4 个答案:

答案 0 :(得分:4)

  

我能使用set的find()来搜索对象吗?我只为operator()提供了实现。这还够吗?

是的,只为comparator课程提供仅operator ()(A&,A&)的实施就足够了。请参阅默认比较器std::less<>

  

有人可以解释在这种情况下find()的工作原理吗?

非常简单的说法:std::set<T,comparator>::find(k)当且仅当两个比较都失败时才返回迭代器it

  1. false ==比较器(k,* it)
  2. false ==比较器(* it,k)
  3. 否则返回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"
}