使用较新的C ++功能,您经常将函数作为参数提供,例如:
// File A.cpp
void do_something(Foo* foo) { ... }
void A::process_foo(){
for_each( foo_list.begin(), foo_list.end(), do_something );
}
但是当我使用类时,我应该在哪里实际放置函数do_something(...)
?我不能把它变成私有成员,因为在将参数传递给for_each时我会松开this
。
所以我倾向于在我的实现文件A.cpp中定义一个普通函数do_something(...)
,就像上面的代码中给出的那样。由于只有A的实现才能看到这一点,所以我不会冒命名空间污染的风险。由于其他类中的类似函数也只能在其实现中可见,因此我也不会冒与其他类的类似函数发生名称冲突的风险。
这是正确的方法吗?
另一个想法是使用Lambda。我对Lambdas不是很熟悉,所以我不知道我是应该尽可能多地使用它们,还是只在绝对必要的时候使用它们......
答案 0 :(得分:1)
std::for_each
的第三个参数需要是具有一个参数的函数或函数对象,例如可以使用for_each
的前两个参数定义的范围元素调用它。然后您有以下选项(假设foo_list
存储Foo*
):
使用常规功能
void do_someting(Foo*){...}
for_each(..., do_something);
您可以将功能放在任何合适的位置。如果这是供本地使用,则匿名命名空间是最佳选择。但它可能是例如在一个单独的编译单元中定义。
使用静态方法
static void do_something(Foo*){...}
for_each(..., &Foo::do_something);
请注意,它不一定是Foo
的静态方法。
使用lambda
for_each(...,[](Foo* f){...});
使用Foo类的方法(甚至私有)和 std::bind
void method(){...}
for_each(..., std::bind(&Foo::method, _1));
还有其他选择,但这些选项最常见。
答案 1 :(得分:1)
C ++ 11解决方案
如果您可以使用C ++ 11,则更喜欢基于范围而不是std::for_each
,并且只需编写代码就行。像这样:
for (const auto& value : foo_list)
{
// do something with the value
}
它不那么冗长,也更方便。它逐个迭代所有元素,就像std::for_each
算法一样。您可以通过const auto&
或简单地auto
(无需参考)明确指定您不想修改元素。
<强>偏-C ++ 11 强>
如果您的编译器不支持基于范围的fors,但支持lambdas(如Visual Studio 2010),只需将函数放入lambda:
for_each( foo_list.begin(), foo_list.end(),
[] (const FooList::value_type& value) { /* do something with the value */; });
<强> C ++ 98 强>
如果您不能使用上述C ++ 11功能,那么大多数STL算法看起来都很可怜。无论您将do_something
函数置于何处,它都将与调用代码分离,这很难阅读。在这种情况下,首选基于简单迭代器:
for (FooList::iterator pValue = foo_list.begin(); pValue != foo_list.end(); ++pValue)
{
// do something with the pValue
}
PS 我更喜欢后一种形式,即使对于&#34; Partial-C ++ 11&#34; case,当你不能使用基于范围的fors时,可以用简单的FooList::iterator
替换auto
。当你不得不写一些更复杂的东西时,这是非常有用的,比如std::list<std::string>::const_iterator
。我认为以下内容优于std::for_each
lambda:
for (auto pValue = foo_list.begin(); pValue != foo_list.end(); ++pValue)
{
// do something with the pValue
}