我正在尝试使用std :: copy_if(),我在某种程度上弄清楚http://www.cplusplus.com/reference/algorithm/copy_if/语法是如何工作的:
auto it = std::copy_if (foo.begin(), foo.end(), bar.begin(), [](int i){return !(i<0);} );
最后一个论点是我感到困惑的一个。括号是什么?我可以使用我在其他地方写的函数作为参数吗?它会如何工作?如果我指定要传递给它的变量,我可以将另一个参数传递给函数吗?
我想我的整体问题是我可以找到这些东西的语法。使用这个例子,我可以声明一些非常简单的东西,但我希望能够用它做更多的事情。我发现了一些地方可以解释一元谓词应该做什么和不做什么,但实际上并不是如何声明一个以及那将意味着什么。我对c ++中的算法还有些新意,希望学习如何更有效地使用它们。
答案 0 :(得分:4)
您可以将任何与函数类似的谓词传递给copy_if
。您可以使用一些常见的东西:
1)功能
函数确实像函数一样,因此它们可以作为谓词传递给copy_if
:
bool is_less_than_zero(int i) { return i < 0; }
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b), is_less_than_zero);
// now b will contain the elements {-2, -1}
}
2)重载operator()
对象可以重载operator()
,以便它们像函数一样运行。这些通常被称为“函数对象”或“函子”。这使您可以存储使用原始函数无法实现的状态:
struct IsLessThan {
IsLessThan(int i) : i_{i} {}
bool operator()(int i) { return i < i_; }
int i_;
};
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b), IsLessThan(0));
// now b will contain the elements {-2, -1}
}
3)Lambdas
Lambdas是概念上的匿名函数。实际上,它们只是具有重载operator()
的对象的语法糖,但这使得它们成为使用少量代码创建简单谓词的有用工具:
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
std::copy_if(a.begin(), a.end(), std::back_inserter(b),
[](int i){ return i < 0; });
// now b will contain the elements {-2, -1}
}
由于lambdas实际上是具有重载operator()
的对象,因此它们也可以包含状态,这是通过lambda的捕获列表给出的:
int main() {
std::vector<int> a = {1, 2, -2, -1};
std::vector<int> b;
int number_to_compare_to = 0;
std::copy_if(a.begin(), a.end(), std::back_inserter(b),
[number_to_compare_to](int i){ return i < number_to_compare_to; });
// now b will contain the elements {-2, -1}
}
标准库中有一些工具可以轻松创建包含状态的函数对象,并使用它来为函数提供一些参数(即std::bind
),但大多数地方它们现在都很有用了更容易使用lambda。也就是说,以下代码创建了两个行为完全相同的对象:
bool first_less_than_second(int i, int j) { return i < j; }
int main() {
auto bind_less_than_zero = std::bind(first_less_than_second, std::placeholders::_1, 0);
auto lambda_less_than_zero = [](int i){ return first_less_than_second(i, 0); };
}
一般情况下,您应该更喜欢lambda版本,但有时您仍会看到std::bind
(或其前c ++ 11提升对应boost::bind
)。