STL使用过度会有什么问题?

6

我使用了很多与std::for_eachbind等相关的STL代码,但我注意到有时候使用STL并不是一个好主意。

例如,如果你有一个std::vector并且想对每个向量项执行一项操作,你的第一个想法可能是使用以下代码:

std::for_each(vec.begin(), vec.end(), Foo())

它很优雅,可以用一段时间。但随之而来的是第一组错误报告,您需要修改代码。现在您应该添加参数来调用Foo(),所以现在变成:

std::for_each(vec.begin(), vec.end(), std::bind2nd(Foo(), X))

但这只是一个临时解决方案。现在项目正在成熟,您对业务逻辑有了更好的理解,并且想要向代码添加新的修改。此时,您意识到应该使用旧的好方法:

for(std::vector::iterator it = vec.begin(); it != vec.end(); ++it)

这只发生在我身上吗?你的代码中是否也有类似的模式?使用STL时,您是否遇到过类似的反模式?


1
顺便提一下,在你的第二个例子中,如果“X”对于所有元素都相同。只需将其传递给Foo的构造函数并将其存储在函数对象中,而不是绑定它。这样会简单得多。 - Evan Teran
你实际上没有使用任何STL,所以你很安全 :) - Lightness Races in Orbit
只是个人意见,"太多"是指你仅仅为了使用它们而使用不需要的功能。如果有帮助,请使用它。如果你担心名称过长,你可以使用typedef或命名空间别名来缩短它们(例如,typedef std::vector::iterator VecIter;)。标准库的问题在于,通常它是在给定编译器上完成某些事情的最干净的一般方式,因为编译器的创建者或最了解它的人(如果不是创建者)将编写其实现。当有用时,不要害怕使用它。 - Justin Time - Reinstate Monica
9个回答

10

使用boost::bind和std::for_each一起,可以干净地解决这个问题。或者你也可以使用BOOST_FOREACH

std::for_each的示例:

std::for_each(v.begin(), v.end(), boost::bind(&C::f, _1, param));

BOOST_FOREACH的示例:

std::list<int> list_int( /*...*/ );
BOOST_FOREACH( int i, list_int )
{
    // do something with i
}

直到你达到10个参数为止,就是这样! :) - Kylotan
1
在哪个时候你将它们组合到一个结构体中 :) - Brian R. Bondy
2
不,这时候你需要重新考虑那个需要一个函数有10个参数的架构了 ;) - Joris Timmermans
这正是我所做的。std::for_each 太丑了。BOOST_FOREACH 好多了。 - Gustavo Muenz

10

不过它也可以反过来。假设您从一个只需要几行代码的操作开始。您不想麻烦地创建一个仅被调用一次的函数来缩短循环,因此您会写出类似以下的代码:

for ()
{
    // do
    // some
    // stuff
}

随着您需要执行的操作变得更加复杂,您意识到将其提取到单独的函数中是合理的,因此最终会得到:

for ()
    do_alot_more_stuff();

然后将其修改为类似于您原始方法的方式,以进一步压缩它的意义是有意义的:

std::for_each(begin, end, do_alot_more_stuff);

最终,将for_each改成for循环或将其反过来,实际上有多难?不要因微小的细节而自责!


5

像其他语言工具一样使用它。当它让生活更轻松时,请使用它。当它变得繁琐时,请换一种方法。当需求发生变化时,重构循环并不是什么难事。


没错。改变代码有什么问题吗? - Adam Jaskiewicz

3

和你的问题类似,我经常注意到在C ++中,“函数对象”模式/习惯用法实际上相当笨拙。这就是为什么我期待C ++ 0X中的Lambda Functions。现在有一些用boost :: lambda可以实现的功能。


天啊,语法... 0X 还有8个月才结束,再加上3年以上等主要编译器厂商跟进。那将是很长一段时间。 - Anton Gogolev
1
@Anton:它已经在g++和Visual Studio 10(现在可以免费获得RC)中了。 - Simon Buchan

2

我在算法相关的很多内容上遇到了同样的问题。它很容易变成比使用老式的for循环还要复杂的代码。

我不能为了避免一个一行的for循环就去创建一些特殊的函数类(这是C++中一个相对高级的话题,我的许多维护者可能不会完全理解),并且需要一个适当的构造函数和析构函数,也许还需要一些访问器。


1
也许你一开始应该使用 transform 而不是 for_each...

1

我很少使用std::for_each。

我建议现在使用Boost.Foreach和经典的“for”结构。当C++0x发布后,您可以考虑使用新的“for”结构,使迭代容器更易读。


1
迫不及待地想要C++得到一个真正的“for”循环(而不是它现在拥有的那种被吹嘘的while循环)。 - T.E.D.

0
同时考虑并行性,使用函数可以定义哪些内容会发生变化,并指示是否可以将一系列元素并行处理,而不是从开始到结束逐个进行处理。

0

或者您可以等待C++0x并使用for(elem& e, container){e.something();}
这与BOOST_FOREACH()非常相似,但是它是标准的一部分(在几年后...)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接