从std::向量中的每个结构中选择一个成员到另一个向量中

selecting a single member from each structure in a std::vector into another vector

本文关键字:向量 一个 另一个 成员 结构 std 选择      更新时间:2023-10-16

我有一个Visual Studio 2008 C++项目,我想将该结构类型的向量的一个结构元素复制到一个新向量中。例如:

struct Foo {
    int a;
    long b;
};
std::vector< Foo > v1;
std::vector< long > v2;
for( std::vector< Foo >::const_iterator it = v1.begin(); it != v1.end(); ++it )
{
    v2.push_back( it->b );
}

还有比这更好/更优雅的方式吗?

谢谢,PaulH

在Visual C++2008中,不,这是最"优雅"的。标准库提供了可用于操作容器的算法,但在大多数情况下——尤其是在像这样的简单用例中——它们太麻烦了,无法使用。

C++11将lambda表达式添加到C++中。Visual C++2010和其他C++编译器的最新版本支持此C++11功能。使用lambda表达式,您可以很容易地将transform算法用于您的任务:

std::transform(v1.begin(), v1.end(), std::back_inserter(v2),
               [](Foo const& x) { return x.b; });

如果没有lambda表达式,则必须定义一个函数来从结构中提取b元素:

long get_b(Foo const& x) { return x.b; }

然后,您可以将此函数与transform算法一起使用:

std::transform(v1.begin(), v1.end(), std::back_inserter(v2), get_b);

然而,对于像这样的简单用例,这可能会很快导致代码变得笨拙,因为很难将所有相关函数整齐地放在一起。

这实际上取决于"更好"的含义。

如果你的意思是,如果同样的东西可以通过使用模板技巧来编写,那么答案是肯定的:

template<typename C, typename T>
struct MemberGetter
{
    T C::*mp;
    MemberGetter(T C::*mp) : mp(mp) { }
    T operator()(const C& c) { return c.*mp; }
};
struct Foo
{
    double dm;
};
...
std::vector<double> x;
std::vector<Foo> y;
std::transform(y.begin(), y.end(),
               std::back_inserter(x),
               MemberGetter<Foo, double>(&Foo::dm));

在我看来,这比显式循环更糟糕,但它的优点是成员指针(即,您正在复制结构的哪一部分)可以是运行时参数。

如果你需要复制的成员是已知的并且是固定的,那么我认为显式循环是最好的方法(我几乎无法想象使用类似模板的情况,其中成员指针是模板参数)。