C++如何用谓词提取struct vector子集生成对应指针vector?
实现方案
C++ 标准库没有提供单步完成「筛选+转换」的独立算法,但可以通过现有标准组件组合实现,以下是两种常用的声明式实现方案:
C++20 范围库方案(最符合声明式需求)
C++20 引入的范围库可以直接组合过滤、转换操作,代码可读性最高,完全不需要手动控制遍历、插入逻辑:
#include <vector> #include <ranges> typedef struct { int a; char b; } some_struct_t; int main() { std::vector<some_struct_t> v = { {10, '1'}, {5, '2'} }; // 先过滤符合条件的元素,再逐个取地址,最后转为指针vector auto v2 = v | std::views::filter([](const some_struct_t& s) { return s.a == 5; }) | std::views::transform([](some_struct_t& s) { return &s; }) | std::ranges::to<std::vector<some_struct_t*>>(); }
C11~C17 兼容方案
如果用不了 C++20,可以用std::for_each实现,逻辑清晰无额外依赖:
#include <vector> #include <algorithm> typedef struct { int a; char b; } some_struct_t; int main() { std::vector<some_struct_t> v = { {10, '1'}, {5, '2'} }; std::vector<some_struct_t*> v2; v2.reserve(v.size()); // 预先分配空间优化性能 std::for_each(v.begin(), v.end(), [&v2](some_struct_t& s) { if (s.a == 5) { v2.push_back(&s); } }); }
如果需要可复用的泛用算法,也可以自行封装符合你需求的模板函数:
template <typename InputIt, typename OutputIt, typename Pred, typename Transform> void filter_transform(InputIt first, InputIt last, OutputIt d_first, Pred pred, Transform trans) { for (; first != last; ++first) { if (pred(*first)) { *d_first++ = trans(*first); } } } // 调用示例 filter_transform(v.begin(), v.end(), std::back_inserter(v2), [](const some_struct_t& s) { return s.a == 5; }, [](some_struct_t& s) { return &s; } );
注意事项
- 你保存的是原 vector 元素的裸指针,需要保证原 vector 的生命周期长于指针 vector v2,且原 vector 没有发生元素增删导致的内存重分配,否则指针会悬空引发未定义行为。
- 如果需要指针和原元素的生命周期绑定,可以考虑使用
std::shared_ptr/std::unique_ptr存储原 vector 元素,或者改用下标索引代替裸指针。
内容的提问来源于stack exchange,提问作者glades
相关产品推荐
相关产品推荐

