如何处理 std::find_if() 返回 false?

How to handle std::find_if() returning false?

以下示例取自 the cplusplus.com reference page 并更改为 return false:

// find_if example
#include <iostream>     // std::cout
#include <algorithm>    // std::find_if
#include <vector>       // std::vector

bool IsOdd (int i) {
  return ((i%2)==1);
}

int main ()
{
  std::vector<int> myvector;    
  myvector.push_back(10);
  myvector.push_back(20);
  myvector.push_back(40);
  myvector.push_back(50);

  std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
  std::cout << "The first odd value is " << *it << '\n';

  return 0;
} 

由于 myvector 中没有任何值是奇数,因此它将 return InputIterator last,这是未定义的:

The first odd value is -1727673935

处理此输出的正确方法是什么?

我怎么知道 std::find_if() returned false 如果输出是不可预测的并且与整个向量进行比较以确认结果值不存在会破坏使用的目的std::find_if() 开始?

你是说

std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);

if ( it != myvector.end() )
{
    std::cout << "The first odd value is " << *it << '\n';
}
else
{
    // std::cout << "there is no odd value in the vector\n";
}

std::find_if returns(reference cppreference.com)

Iterator to the first element satisfying the condition or last if no such element is found.

这意味着,仅当迭代器 不等于 container.end() 迭代器时才取消引用迭代器。

if (const auto iter = std::find_if(myvector.cbegin(), myvector.cend(), IsOdd); // need C++17 compiler support
    iter != myvector.cend())
{
    std::cout << *iter << "\n";
}
else
{
    // code
}

PS:在现代C++中,lambdas表达式应该是你的好朋友,在合适的时候使用它。 在此处查看更多信息:Why can lambdas be better optimized by the compiler than plain functions?

这意味着您的 IsOdd 本来可以

constexpr auto isOdd = [](const int i) /* noexcept */ { return i & 1; };

执行此操作的惯用方法是检查迭代器是否等于结束标记。

auto it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
if (it == myvector.end()) {
    std::cout << "No odd values found" << std::endl;
} else {
    std::cout << "The first odd value is " << *it << std::endl;
}

在 C++17(最新标准)中,您可以在 if 语句中声明迭代器:

if (auto it = std::find_if(myvector.begin(), myvector.end(), IsOdd); it != myvector.end()) {
    std::cout << "The first odd value is " << *it << std::endl;
} else {
    std::cout << "No odd values found" << std::endl;
}

您需要检查返回的迭代器是否是您传递给 std::find_if(第二个参数)的结束迭代器。这些语义对于标准库中的算法来说是很常见的,所以你应该习惯这一点。

const auto firstOdd = std::find_if (myvector.cbegin(), myvector.cend(), IsOdd);

if (firstOdd != myvector.cend())
    std::cout << "The first odd value is " << *it << '\n';
else
    std::cout << "No odd values found\n";

另请注意,您可以使用 cbegin()/cend() 成员函数,因为您不会改变容器。