如何从C++结构体数组中高效提取指定元素的数组
问题描述
现有如下结构体及vector:
struct cell{ int pos; int id; }; std::vector<cell> myArray;
需要从中提取所有id元素组成std::vector<int>,并传入要求该类型参数的函数myFunc。但直接遍历原数组拷贝耗时过长,因此希望找到更高效的实现方式。
曾尝试通过创建指向id的指针数组std::vector<int*>,再将其转换为std::vector<int>,但遍历指针数组转换的过程同样耗时。
核心诉求:高效从结构体vector中提取指定成员的vector,避免耗时的遍历拷贝(或找到最优的转换方式)。
解决方案
首先必须明确:不存在不遍历就能生成std::vector<int>的方法。原因是std::vector<int>要求内部是连续的内存块,但原myArray中每个cell的id在内存中是按sizeof(cell)的间隔分布的,并非连续存储。要将分散的id整合到连续内存中,必然需要逐个拷贝元素,这个过程无法绕过遍历。
最优的拷贝实现方式
如果必须生成std::vector<int>,以下是最高效的实现方式,比手动遍历或指针数组转换更高效:
std::vector<int> idsArray; idsArray.reserve(myArray.size()); // 提前分配足够内存,避免多次扩容 std::transform(myArray.begin(), myArray.end(), std::back_inserter(idsArray), [](const cell& c) { return c.id; }); myFunc(idsArray);
reserve提前分配内存,避免vector在扩容时的内存拷贝开销;std::transform是STL优化过的算法,性能接近手动遍历,且代码更简洁。
替代思路(若可修改函数参数类型)
如果允许修改myFunc的参数类型,可以避免拷贝,直接传递原数组中id的视图:
- C++20及以上:使用
std::views::transform生成视图,再用std::span传递:
#include <ranges> #include <span> // 修改myFunc参数为std::span<const int> void myFunc(std::span<const int> ids); // 生成视图并传递 auto ids_view = myArray | std::views::transform([](const cell& c) { return c.id; }); myFunc(std::span(ids_view));
这种方式无需拷贝任何元素,仅在访问时动态获取id,完全避免拷贝耗时,但前提是函数支持接受视图类参数。
关于指针数组方案的说明
你之前尝试的指针数组转换方案,本质上和直接遍历原数组拷贝的耗时是一致的——甚至更慢,因为多了一层指针解引用的开销,同时还额外占用了存储指针的内存。因此不推荐使用该方案。
内容的提问来源于stack exchange,提问作者Rafael
相关产品推荐
相关产品推荐

