【问题标题】:std::find not using my defined == operatorstd::find 不使用我定义的 == 运算符
【发布时间】:2013-07-31 22:01:09
【问题描述】:

我有一个简单的类,我将它作为指针存储在向量中。我想在向量上使用 find 但找不到我的对象。在调试时,它似乎没有调用我提供的 == 运算符。我可以在调试器中“看到”对象,所以我知道它在那里。下面的代码甚至使用了列表中第一项的副本,但仍然失败。我可以让它通过的唯一方法是使用 MergeLine* mlt = LineList.begin(),这表明它正在比较对象而不是使用我的相等运算符。

class MergeLine {
public:
   std::string linename;
   int StartIndex;
   double StartValue;
   double FidStart;
   int Length; 

   bool operator <  (const MergeLine &ml) const {return FidStart < ml.FidStart;}
   bool operator == (const MergeLine &ml) const {
         return linename.compare( ml.linename) == 0;}    
};

Class OtherClass{
public:
   std::vector<MergeLine*>LineList;
   std::vector<MergeLine*>::iterator LL_iter;
   void DoSomething( std::string linename){
 // this is the original version that returned LineList.end()
 //   MergeLine * mlt
 //   mlt->linename = linename;

 // this version doesn't work either (I thought it would for sure!)
      MergeLine *mlt =new MergeLine(*LineList.front());
      LL_iter = std::find(LineList.begin(), LineList.end(), mlt);
      if (LL_iter == LineList.end()) {
         throw(Exception("line not found in LineList : " + mlt->linename));
      }
      MergeLine * ml = *LL_iter;

    }
};

干杯, 马克

【问题讨论】:

  • 当然不是。 a == b*a == *b 不同...
  • 指针是内置类型,所以它们不使用重载的operator==
  • 您将向量指针存储在指向 MergeLine 而不是普通 MergeLine 对象中的任何特殊原因?再说了,不就是一个更适合你需求的智能指针吗?
  • @Antonio,坦率地说,我不记得我为什么将它实现为指针。回顾我的代码,我可以很容易地将它重新实现为对象。我可能会这样做。
  • 注意:表达式linename.compare( ml.linename) == 0可以更简单地写成linename == ml.linename

标签: c++ stl std


【解决方案1】:

由于您的容器包含指针而不是对象,因此比较将在指针之间进行。指针相等的唯一方法是它们指向完全相同的对象。正如您所注意到的,对象本身的比较运算符永远不会被调用。

您可以使用std::find_if 并将其传递给比较对象以供使用。

class MergeLineCompare
{
    MergeLine * m_p;
public:
    MergeLineCompare(MergeLine * p) : m_p(p)
    {
    }
    bool operator()(MergeLine * p)
    {
        return *p == *m_p;
    }
};

LL_iter = std::find_if(LineList.begin(), LineList.end(), MergeLineCompare(mlt));

【讨论】:

    【解决方案2】:

    我认为你真正想要的是像这样使用std::find_if

    struct MergeLineNameCompare
    {
        std::string seachname;
    
        MergeLineNameComp(const std::string &name) : seachname(name)
        {
        }
    
        bool operator()(const MergeLine * line)
        {
            return seachname.compare( line->linename ) == 0;
        }
    };
    
    LL_iter = std::find_if(LineList.begin(), LineList.end(), MergeLineNameCompare(linename) );
    

    operator ==(无论是哪种形式)更好地保存以进行真正的相等比较。

    【讨论】:

    • 你的答案是正确的,但马克的更容易理解。谢谢。
    • 是的,不幸的是,@mark-ransom 的回答并不完全正确。
    • 他没有注意它是打算按名称找到 MergeLine 的,并且正在使用 operator == 的基本不幸运的实现。
    • 运营商通常应该按照他们说的去做,...而当operator ==迟早被更改以进行更深入的比较时,他的代码的含义也会发生变化。
    【解决方案3】:

    运算符重载不能使用指针,因为它是模棱两可的。

    Bjarne Stroustrup :-

    引入引用主要是为了支持运算符重载。 C按值传递每个函数参数,以及传递对象的地方 按价值计算会效率低下或不合适,用户可以通过 指针。此策略在运算符重载的情况下不起作用 用过的。在这种情况下,符号方便是必不可少的,以便用户 如果对象是,则不能期望插入运算符的地址 大。

    所以,可能不是最好的,但仍然:-

       std::vector<MergeLine>LineList;
       std::vector<MergeLine>::iterator LL_iter;
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2019-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-18
      • 2016-10-02
      • 2017-08-20
      • 2020-04-17
      相关资源
      最近更新 更多