如何为int类型的vector of vectors预分配空间,避免不必要的system calls
解决方案:用视图替代嵌套vector避免多次内存分配
核心思路是不要创建实际的嵌套vector,而是用「视图」指向原vector的连续区间——嵌套vector必然会为每个子容器分配独立内存,而视图仅存储指针和长度,完全复用原vector的内存,零额外动态分配开销,完美避免不必要的system call。
为什么嵌套vector无法实现单次分配
每个vector<int>都有独立的内存缓冲区,哪怕用自定义分配器,也需要为每个子vector至少分配一次内存(除非实现复杂的内存池,得不偿失)。此外,如果外层vector未预分配空间,push_back子vector时还会触发扩容,带来额外分配操作。
最优方案:C++20 std::span(推荐)
std::span是C++20引入的非拥有型视图,专门用于表示连续内存区间,本身不持有内存,仅存储原数据的指针和长度。外层使用vector<span<int>>,预先reserve足够空间后,只会做一次内存分配(用于存储外层vector的span元素),完全无额外system call。
示例代码:
#include <vector> #include <span> #include <iostream> int main() { std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::vector<std::span<int>> groups; // 预分配外层vector的空间,避免扩容 groups.reserve((nums.size() + 2) / 3); const size_t group_size = 3; size_t start = 0; while (start < nums.size()) { size_t end = std::min(start + group_size, nums.size()); // 直接构造span,无额外内存分配 groups.emplace_back(nums.data() + start, end - start); start = end; } // 客户端遍历代码几乎和原需求一致 for (auto subspan : groups) { for (auto num : subspan) { std::cout << num << " "; } std::cout << "\n"; } return 0; }
C++20之前的替代方案:自定义极简视图类
如果无法使用C++20,可自行实现一个简单的视图类,只需支持范围for循环的基本接口即可,效果与span完全一致:
#include <vector> #include <iostream> #include <algorithm> // 用于std::min template<typename T> struct RangeView { T* data; size_t size; // 支持范围for循环的必要接口 T* begin() const { return data; } T* end() const { return data + size; } // 可选:支持下标访问 T& operator[](size_t idx) const { return data[idx]; } }; int main() { std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; std::vector<RangeView<int>> groups; groups.reserve((nums.size() + 2) / 3); const size_t group_size = 3; size_t start = 0; while (start < nums.size()) { size_t end = std::min(start + group_size, nums.size()); groups.push_back({nums.data() + start, end - start}); start = end; } // 客户端遍历逻辑完全不变 for (auto subview : groups) { for (auto num : subview) { std::cout << num << " "; } std::cout << "\n"; } return 0; }
兼容性说明
客户端的遍历代码几乎无需修改,仅需将原来的subvector替换为subspan或subview即可,遍历逻辑与原需求完全一致,满足业务场景。
内容的提问来源于stack exchange,提问作者khajiit
相关产品推荐
相关产品推荐

