C++,find_if 不工作

发布于 2024-10-04 19:15:00 字数 1313 浏览 2 评论 0原文

我第一次在 C++ 代码中使用 std::find_if 函数。我想要执行的示例和逻辑非常简单,但不知何故我无法使其工作。

我以这种方式创建了“finder”类:

  /**
  * @class message_by_id_finder
  * @brief A class to find the matching lane wrapper
  */
  class message_by_id_finder
  {
  public:
  /** @brief constructor */
  explicit message_by_id_finder(int id) :
  m_myMessage(id) {
  }

  /** @brief the comparing function */
  bool operator()(const AppMessage& message) const {
  return message.messageId == m_myMessage;
  }

  private:
  /// @brief The id of the searched object
  int m_myMessage;
  };

然后我按以下方式使用它:

 // Loop messages 
for (vector<AppMessage>::iterator it = messages.begin(); it != messages.end() ; ++it ) {
// Match message with the registered by the App
AppMessage m = *it;
vector<AppMessage>::iterator it2 = find_if(m_messages.begin(), m_messages.end(), message_by_id_finder(m));
if (it2 != m_messages.end()) {
  // FOUND!
} else {
  // NOT FOUND
}
} 

我循环 m_messages 向量,并且有与 id 匹配的成员,但 it2 始终为 0x00。我做错了什么吗?

预先非常感谢您。

PD:以防万一,其他代码有助于理解问题:

  /**
  * @struct AppMessage
  * @brief Information of a message carrying a result of the App.
  */
  struct AppMessage {
      int messageId;      
      float payloadValue;    
  };

I am using for the first time std::find_if function in C++ code. The examples and the logic I want to execute are pretty simple but somehow I cannot make it work.

I have created the "finder" class this way:

  /**
  * @class message_by_id_finder
  * @brief A class to find the matching lane wrapper
  */
  class message_by_id_finder
  {
  public:
  /** @brief constructor */
  explicit message_by_id_finder(int id) :
  m_myMessage(id) {
  }

  /** @brief the comparing function */
  bool operator()(const AppMessage& message) const {
  return message.messageId == m_myMessage;
  }

  private:
  /// @brief The id of the searched object
  int m_myMessage;
  };

Then I use it the following way:

 // Loop messages 
for (vector<AppMessage>::iterator it = messages.begin(); it != messages.end() ; ++it ) {
// Match message with the registered by the App
AppMessage m = *it;
vector<AppMessage>::iterator it2 = find_if(m_messages.begin(), m_messages.end(), message_by_id_finder(m));
if (it2 != m_messages.end()) {
  // FOUND!
} else {
  // NOT FOUND
}
} 

I looped the m_messages vector and there are members that match the id but it2 is always 0x00. Am I doing something particulary wrong?

Thank you very much in advance.

PD: Just in case, other piece of codes useful to understand the problem:

  /**
  * @struct AppMessage
  * @brief Information of a message carrying a result of the App.
  */
  struct AppMessage {
      int messageId;      
      float payloadValue;    
  };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清君侧 2024-10-11 19:15:00

您必须了解 find_if 内部的作用才能正确使用它。 cplusplus 参考 站点提供了一些基本的代码片段,可能有助于理解算法的实际作用(但请记住,这只是出于教育目的的“伪代码”,而不是实际的实现)。这就是该网站对 std::find_if 的描述:

template<class InputIterator, class Predicate>
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred )
{
  for ( ; first!=last ; first++ ) if ( pred(*first) ) break;
  return first;
}

您可以看到,为序列中的每个元素调用谓词。在这里,您有一个 std::vector,因此所提供的谓词应该可以使用 AppMessage 进行调用。

将谓词更改为此应该可以解决问题:

class message_by_id_finder
{
public:
    /** @brief constructor */
    explicit message_by_id_finder(int id) :
        m_myMessage(id)
    {}

    /** @brief the comparing function */
    bool operator()(const AppMessage &appMessage) const {
        return appMessage.messageId == m_myMessage;
    }

private:
    /// @brief The id of the searched object
    const int m_myMessage;
}

另请注意,我将 operator()m_myMessage 设置为 const(为什么?因为我可以!)。

You have to understand what find_if does internally in order to use it correctly. The cplusplus reference site offers some basic code snippets which may help understand what an algorithm actually does (but remember it's just 'pseudo-code' for educational purpose, not the actual implementation). This is what this site gives as a description of std::find_if :

template<class InputIterator, class Predicate>
InputIterator find_if ( InputIterator first, InputIterator last, Predicate pred )
{
  for ( ; first!=last ; first++ ) if ( pred(*first) ) break;
  return first;
}

What you can see is that the predicate is called for each element in the sequence. Here, you have a std::vector<AppMessage> so the provided predicate should be callable with an AppMessage.

Changing you predicate to this should do the trick :

class message_by_id_finder
{
public:
    /** @brief constructor */
    explicit message_by_id_finder(int id) :
        m_myMessage(id)
    {}

    /** @brief the comparing function */
    bool operator()(const AppMessage &appMessage) const {
        return appMessage.messageId == m_myMessage;
    }

private:
    /// @brief The id of the searched object
    const int m_myMessage;
}

Also note that I made operator() and m_myMessage const (why ? because I can !).

半暖夏伤 2024-10-11 19:15:00

您的谓词应该采用迭代类型的对象,在您的情况下是 AppMessage。

因此,如果你用这样的东西替换你的operator(),我想你会更接近一些有效的东西:

bool operator()(const AppMessage& am) const {
    return am.messageId == m_myMessage;
}

Your predicate should take an object of the type iterated over, that is an AppMessage in your case.

So if you replace your operator() with something like this, I think you'll get closer to something working:

bool operator()(const AppMessage& am) const {
    return am.messageId == m_myMessage;
}
鹤舞 2024-10-11 19:15:00

find_if 的布尔逻辑是错误的,这很可能导致您的错误。

事实上,如果您的向量不是很短并且您执行此操作很多次,则 find 和 find_if 效率非常低,因为它们是线性复杂度。你的使用了 2 个循环,这使得它的复杂度为 O(M*N),其中 M 和 N 是你的集合的长度。

Big-O,顾名思义,是高效编程的关键之一。

如果您的集合都已排序,则 set_intersect 是获取两个集合中的所有项目的方法,其时间复杂度为 O(M+N)。如果不是,您可以对其中之一进行排序,然后您的查找将是 O(M log N) 或 O(N log M),具体取决于您排序的哪一个。如果一个比另一个长得多,并且对较长的一个进行排序,则 O(M log N) 比 O(M + N) 更有效(典型情况是在具有大量记录的数据库表中搜索一些项目与几次索引查找相比,即使运行一次表也会效率低下)。

Your boolean logic is wrong for find_if which is most likely leading to your error.

As it is, if your vectors are not very short and you are doing this a lot of times, find and find_if are very inefficient as they are linear complexity. Yours uses 2 loops which makes it O(M*N) where M and N are the length of your collections.

Big-O, as it is called, is one of the main keys to efficient programming.

If your collections are both sorted, set_intersect is the way to get all the items that are in both collections which is O(M+N). If they are not, you can sort one of them then subsequently your lookup will be O(M log N) or O(N log M) dependent on which one you sorted. If one is much longer than the other and you sort the longer one, O(M log N) is more efficient than O(M + N) (typical situation is searching for a few items in a database table that has a lot of records. Even running the table once is going to be inefficient compared to a few indexed lookups).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文