13

假设我有以下对象:

struct Foo
{
    int size() { return 2; }
};

size获取a 中所有对象的总和的最佳方法是什么(最可维护、最易读等)vector<Foo>?我会发布我的解决方案,但我对更好的想法感兴趣。

更新:

到目前为止,我们有:

  • std::accumulate 和一个仿函数
  • std::accumulate 和 lambda 表达式
  • 普通的 for 循环

还有其他可行的解决方案吗?你能用boost::bindor做一些可维护的东西std::bind1st/2nd吗?

4

5 回答 5

27

除了您自己的建议之外,如果您的编译器支持 C++0x lambda 表达式,您可以使用这个较短的版本:

std::vector<Foo> vf;

// do something to populate vf


int totalSize = std::accumulate(vf.begin(),
                                vf.end(),
                                0, 
                                [](int sum, const Foo& elem){ return sum + elem.size();});
于 2010-07-08T15:11:08.090 回答
7

使用std::accumulate和仿函数。

#include <functional>
#include <numeric>

struct SumSizes : public std::binary_function<int, Foo, int>
{
    int operator()(int total, const Foo& elem) const
    {
        return total + elem.size();
    }
};

std::vector<Foo> vf;

// do something to populate vf

int totalSize = std::accumulate(vf.begin(),
                                vf.end(),
                                0, 
                                SumSizes());
于 2010-07-08T14:54:04.757 回答
7

我发现 Boost 迭代器很优雅,尽管它们可能有点冗长(基于范围的算法会更好)。在这种情况下,转换迭代器可以完成这项工作:

#include <boost/iterator/transform_iterator.hpp>
//...

int totalSize = std::accumulate(
    boost::make_transform_iterator(vf.begin(), std::mem_fn(&Foo::size)),
    boost::make_transform_iterator(vf.end(), std::mem_fn(&Foo::size)),0);

编辑:将“ boost::bind(&Foo::size,_1)”替换为“ std::mem_fn(&Foo::size)

编辑:我刚刚发现 Boost.Range 库已经更新以引入范围算法!这是同一解决方案的新版本:

#include <boost/range/distance.hpp> // numeric.hpp needs it (a bug?)
#include <boost/range/numeric.hpp> // accumulate
#include <boost/range/adaptor/transformed.hpp> // transformed
//...
int totalSize = boost::accumulate(
    vf | boost::adaptors::transformed(std::mem_fn(Foo::size)), 0);

注意:性能大致相同(请参阅我的评论):在内部,transformed使用transorm_iterator.

于 2010-07-08T23:59:47.197 回答
6

使用 C++11(及更高版本)基于范围的 for 循环

std::vector<Foo> vFoo;
// populate vFoo with some values...
int totalSize = 0;
for (const auto& element: vFoo) {
    totalSize += element.size();
}
于 2016-07-31T23:23:00.343 回答
4

这是实际的解决方案:

typedef std::vector<Foo> FooVector;
FooVector vf;
int totalSize = 0;
for (FooVector::const_iterator it = vf.begin(); it != vf.end(); ++it) {
  totalSize += it->size();
}
于 2010-07-08T15:16:14.753 回答