C++如何从类对象vector中提取特定成员vector且避免显式for循环
实现方案
完全可以通过C标准库组件实现该需求,无需手动编写显式for循环,不同C版本可选的实现方式如下:
C++11及以上兼容版本
使用std::transform即可实现,提前预分配内存可达到和手写for循环完全一致的性能:
#include <vector> #include <algorithm> #include <iterator> struct Foo { double x; double y; }; std::vector<double> bar(const std::vector<Foo>& xy) { std::vector<double> result; result.reserve(xy.size()); // 提前分配足够空间,避免多次扩容开销 std::transform(xy.cbegin(), xy.cend(), std::back_inserter(result), [](const Foo& foo) { return foo.x; }); return result; }
如果不想写lambda,也可以用std::mem_fn直接取成员指针实现相同效果:
std::transform(xy.cbegin(), xy.cend(), std::back_inserter(result), std::mem_fn(&Foo::x));
C++20及以上更简洁的ranges方案
借助标准范围库可以进一步简化代码,无需手动管理插入器和容器预分配:
#include <vector> #include <ranges> #include <algorithm> struct Foo { double x; double y; }; std::vector<double> bar(const std::vector<Foo>& xy) { auto x_view = xy | std::views::transform(&Foo::x); return std::vector<double>(x_view.begin(), x_view.end()); }
如果使用C++23,可以直接用std::ranges::to一步完成容器构造,代码更简洁:
std::vector<double> bar(const std::vector<Foo>& xy) { return xy | std::views::transform(&Foo::x) | std::ranges::to<std::vector>(); }
补充说明
如果后续操作只需要遍历所有x值,不需要持有独立的std::vector<double>,可以直接返回std::views::transform生成的视图,完全避免内存拷贝,性能更高。
内容的提问来源于stack exchange,提问作者P45 Imminent
相关产品推荐
相关产品推荐

