查找具有偶数值的向量元素

Leo*_*ldo 5 c++ algorithm stl bind

你能解释一下这段代码是如何工作的吗?它成功地计算了具有偶数值的向量元素,但我不清楚在这种特殊情况下绑定是如何工作的。

count_if(vec.begin(), vec.end(),
         std::bind(logical_not<bool>(),
                   std::bind(modulus<int>(), placeholders::_1, 2)));
Run Code Online (Sandbox Code Playgroud)

Mr.*_*C64 3

请注意,您发布的代码计算向量中的偶数,不是奇数:

count_if(vec.begin(), vec.end(),
         bind(logical_not<bool>(),
              bind(modulus<int>(), placeholders::_1, 2)));
Run Code Online (Sandbox Code Playgroud)

count_if是一种返回指定范围内满足特定条件的元素数量的算法:

count_if(first, last, criteria)
Run Code Online (Sandbox Code Playgroud)

在你的情况下,firstisvec.begin()lastis vec.end():所以整个向量被考虑用于计数。

现在让我们将注意力集中在标准部分。

从内开始,向外:

modulus<int>是一个返回整数除法余数的函数对象%(就像运算符一样)。它需要两个参数:第一个表示为placeholders::_1,它是源向量中的通用元素。将其视为x扫描整个矢量内容的变量。

第二个参数是 number 2,因为要检查整数是偶数还是奇数,您可以计算x % 2结果并将其与 0 进行比较:

x % 2 == 0 --> even number
x % 2 == 1 --> odd number
Run Code Online (Sandbox Code Playgroud)

bind用于指定modulus函数对象的参数。

此模运算的结果作为另一个函数对象的输入给出:logical_not<bool>。这只是否定输入,例如,如果输入为false(0),则logical_not<bool>返回true,反之亦然。

因此,“计数标准”由以下操作流程表示:

  1. 计算:placeholders::_1 % 2,即<<generic vector element>> % 2,使用modulus
  2. 如果上述操作的结果是0(假),则返回true(反之亦然),使用logical_not.

因此,如果一个数是偶数:

  1. even number % 2 == 0
  2. 否定 0 你得到true.

相反,如果一个数字是奇数:

  1. odd number % 2 == 1
  2. 否定 1 你得到false.

由于count_if计算条件为 的元素数量true,因此您正在计算向量中的偶数

如果你真的想计算向量中的奇数,你可以去掉逻辑反转(即logical_not):

auto odds = count_if(vec.begin(), vec.end(),
                     bind(modulus<int>(), placeholders::_1, 2));    
Run Code Online (Sandbox Code Playgroud)

modulus请注意,在这种情况下,使用and的函数方法logical_not似乎太复杂:使用lambda(甚至是一个临时的 IsEven() 简单函数)会更清晰。
考虑以下代码(位于 Ideone 上)来比较这三种方法:

#include <algorithm>
#include <functional>
#include <iostream>
#include <vector>
using namespace std;

bool IsEven(int n) {
    return (n % 2) == 0;
}

int main() {
    // Test vector
    vector<int> vec{ 11, 22, 33, 44, 55 };

    // Using functional approach
    auto n = count_if(vec.begin(), vec.end(),
         bind(logical_not<bool>(),
             bind(modulus<int>(), placeholders::_1, 2)));    
    cout << n << endl;

    // Using lambdas
    n = count_if(vec.begin(), vec.end(), 
                 [](int n) { return (n % 2) == 0; });
    cout << n << endl;

    // Using boolean returning ad hoc function
    n = count_if(vec.begin(), vec.end(), IsEven);
    cout << n << endl;
}
Run Code Online (Sandbox Code Playgroud)