从std::vector中的每个结构中选择一个成员到另一个向量中 我有一个VisualStudio 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 ); } structfoo{ INTA; 长b; }; std::vectorv1; std::vectorv2; 对于(std::vector::const_迭代器it=v1.begin();it!=v1.end();++it) { v2.推回(it->b); }
有比这更好/更优雅的方式吗 谢谢,从std::vector中的每个结构中选择一个成员到另一个向量中 我有一个VisualStudio 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 ); } structfoo{ INTA; 长b; }; std::vectorv1; std::vectorv2; 对于(std::vector::const_迭代器it=v1.begin();it!=v1.end();++it) { v2.推回(it->b); },c++,stl,C++,Stl,有比这更好/更优雅的方式吗 谢谢, PaulH < P>在Visual C++ 2008中,不,这是“优雅”的。标准库提供了可用于操作容器的算法,但在大多数情况下——特别是在像这样的简单用例中——它们太麻烦而无法使用 C++ 11将lambda表达式添加到C++中。Visual C++ 2010和其他C++编译器的最新版本支持C++ 11的特性。使用lambda表达式,您可以轻松地使用变换算法执行任务: std::transform(v1.begin(), v1.end(), std::ba
PaulH < P>在Visual C++ 2008中,不,这是“优雅”的。标准库提供了可用于操作容器的算法,但在大多数情况下——特别是在像这样的简单用例中——它们太麻烦而无法使用
C++ 11将lambda表达式添加到C++中。Visual C++ 2010和其他C++编译器的最新版本支持C++ 11的特性。使用lambda表达式,您可以轻松地使用
变换
算法执行任务:
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; }
然后,您可以将此函数与变换算法一起使用:
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));
模板
结构成员获取程序
{
TC::*mp;
MemberGetter(tc::*mp):mp(mp){}
T运算符()(常量C&C){返回C.*mp;}
};
结构Foo
{
双dm;
};
...
std::向量x;
std::向量y;
std::transform(y.begin(),y.end(),
标准:背面插入器(x),
MemberGetter(&Foo::dm));
在我看来,这比显式循环更糟糕,但其优点是成员指针(即复制结构的哪一部分)可以是运行时参数
如果您需要复制的成员是已知的和固定的,那么我会说显式循环是最好的方法(我几乎无法想象在某些情况下使用类似的模板,其中成员指针是模板参数会有任何意义)。当然,还有其他技术,比如Boost.Lambda,或者编写通用的转换器,并将其与标准库绑定器一起使用,但这些技术都比不上原始代码中的技术。您还可以使用std::bind(&Foo::b)
获得签名函数long&(Foo&)
,我想。我已经试着完全把bind
从我的记忆中抹去,尽管我担心有些伤疤会永远留在我的记忆中-O@Kerrek:当然包括缺少的占位符。@6502:将lambda与转换
一起使用的唯一原因是,它使代码比使用MemberGetter
、std::bind
或相关技术更简单、更容易理解。在大多数情况下,算法优于循环,这是出于同样的原因:它们使代码更清晰、更简单、更容易理解。请参阅我对的回答,了解我为什么主张在循环上使用算法。