请注意,您发布的代码计算向量中的偶数,而不是奇数:
count_if(vec.begin(), vec.end(),
bind(logical_not<bool>(),
bind(modulus<int>(), placeholders::_1, 2)));
count_if 是一种算法,它返回指定范围内满足特定条件的元素数量:
count_if(first, last, criteria)
在您的情况下,first 是 vec.begin() 和 last 是 vec.end():所以整个向量都被考虑用于计数。
现在让我们将注意力集中在条件部分。
由内而外:
modulus<int> 是一个function object,它返回整数除法的余数(就像% 运算符一样)。它有两个参数:第一个表示为placeholders::_1,它是源向量中的通用元素。把它想象成一个变量x,它扫描整个向量内容。
第二个参数是数字2,因为要检查一个整数是偶数还是奇数,你可以计算x % 2并将结果与0进行比较:
x % 2 == 0 --> even number
x % 2 == 1 --> odd number
bind用于指定modulus函数对象的参数。
这个模运算的结果作为输入提供给另一个function object:logical_not<bool>。这只是否定输入,例如如果输入为false (0),则logical_not<bool> 返回true,反之亦然。
因此,“计数标准”由以下操作流程表示:
- 计算:
placeholders::_1 % 2,即<<generic vector element>> % 2,使用modulus。
- 如果上述操作的结果为
0(false),则返回true(反之亦然),使用logical_not。
所以,如果一个数字是偶数:
even number % 2 == 0
- 否定 0 你得到
true。
相反,如果一个数字是奇数:
odd number % 2 == 1
- 否定 1 你得到
false。
由于count_if 计算条件为true 的元素的数量,因此您正在计算向量中的偶数 个数字。
如果你真的想计算向量中的奇数个数,你可以去掉逻辑反转(即logical_not):
auto odds = count_if(vec.begin(), vec.end(),
bind(modulus<int>(), placeholders::_1, 2));
请注意,在这种情况下,使用 modulus 和 logical_not 的函数式方法似乎过于复杂:使用 lambda(甚至是 ad hoc IsEven() simple function)会更清晰。
考虑以下代码 (live here on 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;
}