当前位置:  开发笔记 > 编程语言 > 正文

是否更喜欢STL算法而不是手卷循环?

如何解决《是否更喜欢STL算法而不是手卷循环?》经验,为你挑选了4个好方法。

我似乎在问题和答案中看到比迭代器更多的"for"循环,而不是for_each(),transform()等.Scott Meyers建议使用stl算法,或者至少在2001年做过.当然,使用它们通常意味着将循环体移动到函数或函数对象中.有些人可能觉得这是一种不可接受的并发症,而其他人可能觉得这样可以更好地解决问题.

那么... STL算法应该优于手动循环吗?



1> Kevin..:

这取决于:

是否需要高性能

循环的可读性

算法是否复杂

如果循环不是瓶颈,并且算法很简单(如for_each),那么对于当前的C++标准,我更喜欢手动循环以提高可读性.(逻辑的局部性是关键.)

但是,现在C++ 0x/C++ 11受到一些主要编译器的支持,我会说使用STL算法,因为它们现在允许使用lambda表达式 - 因此也就是逻辑的局部性.


当然.如果它对您更具可读性,那么请使用for_each.我的观点是,在函数范围之外创建一个1-off仿函数只是为了与for_each一起使用会导致问题.但是如果函子已经存在,你使用boost :: lambda,或者你发现远程函子更具可读性,那么使用for_each
有人可能认为(std :: vector :: iterator it = v.begin(); it!= v.end(); ++ it){...}的可读性低于for_each(v. begin(),v.end(),...).

2> Ron Romero..:

我将在这里反对,并提倡使用STL算法和仿函数使代码更易于理解和维护,但你必须正确行事.你必须更加注意可读性和清晰度.特别是,你必须得到正确的命名.但是当你这样做时,你最终会得到更清晰,更清晰的代码,并且范式转变为更强大的编码技术.

我们来举个例子吧.这里我们有一组孩子,我们想把他们的"Foo Count"设置为某个值.标准的for循环迭代器方法是:

for (vector::iterator iter = children.begin();
    iter != children.end();
    ++iter)
{
    iter->setFooCount(n);
}

哪个,是的,它非常清楚,而且绝对不错的代码.只需稍微看一下就可以搞清楚.但是看看我们可以用适当的仿函数做些什么:

for_each(children.begin(), children.end(), SetFooCount(n));

哇,这正是我们所需要的.你不必弄清楚; 你立即知道它正在设定每个孩子的"Foo计数".(如果我们不需要.begin()/ .end()废话,那就更清楚了,但你不能拥有一切,而且在制作STL时他们没有咨询我.)

当然,你确实需要定义这个神奇的仿函数SetFooCount,但它的定义很漂亮:

class SetFooCount
{
public:
    SetFooCount(int n) : fooCount(n) {}

    void operator () (Child& child)
    {
        child.setFooCount(fooCount);
    }

private:
    int fooCount;
};

总的来说,它是更多的代码,您必须查看另一个地方才能确切了解SetFooCount正在做什么.但是因为我们很好地命名,99%的时间我们不必查看代码SetFooCount.我们假设它按照它所说的做,我们只需要查看该for_each行.

我真正喜欢的是使用算法会导致范式转换.您不必将列表视为对象集合,而是对列表的每个元素执行操作,而是将列表视为第一类实体,并直接在列表本身上操作.for循环遍历列表,在每个元素上调用成员函数来设置Foo Count.相反,我正在做一个命令,它设置列表中每个元素的Foo Count.它很微妙,但当你看到森林而不是树木时,你会获得更多的力量.

因此,通过一些思考和仔细的命名,我们可以使用STL算法来制作更清晰,更清晰的代码,并开始在更细粒度的层次上思考.



3> paercebal..:

std::foreach是什么样的代码,让我骂了STL,年前.

我不能说它是否更好,但我更喜欢在循环前导使用我的循环代码.对我来说,这是一个强烈的要求.并且std::foreach构造不允许我(奇怪的是,就我而言,Java或C#的foreach版本很酷......所以我猜它确认了对我来说循环体的局部性是非常重要的).

因此,只有当只有一个可读/可理解的算法可用时,我才会使用foreach.如果没有,不,我不会.但这是一个品味问题,我想,因为我应该更加努力地去理解并学会解析所有这些......

请注意,加速的人显然感觉有点相同,因为他们写了BOOST_FOREACH:

#include 
#include 
#include 

int main()
{
    std::string hello( "Hello, world!" );

    BOOST_FOREACH( char ch, hello )
    {
        std::cout << ch;
    }

    return 0;
}

请参阅:http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html


同意.BOOST_FOREACH是提升IMO的最佳部分.让我更有成效

4> 小智..:

这真是Scott Meyers出错的一件事.

如果存在与您需要做的匹配的实际算法,那么当然使用该算法.

但是如果你需要做的就是遍历一个集合并对每个项目做一些事情,那么只需执行正常的循环而不是尝试将代码分离到另一个函子中,这样就最终将代码切割成比特而没有任何实际的好处.

还有一些其他的选项,比如boost :: bind或boost :: lambda,但那些是非常复杂的模板元编程的东西,它们在调试和单步执行代码时效果不佳所以通常应该避免使用它们.

正如其他人所提到的,当lambda表达式成为一等公民时,这一切都将改变.

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有