如何在不初始化新增元素的情况下调整C++ vector的大小?
问题
我程序中存在一个包含平凡字段的常用数据类型:
struct Element { Element() noexcept : x( 0 ), y( 0 ), z( 0 ) {} float x, y, z; };
同时有大量代码使用Element类型的vector,例如:
void foo( std::vector<Element> & es );
因此对Element进行大幅修改(如更改默认构造函数),或替换所有代码中的std::vector都极为复杂。
在一处性能关键的代码中,我需要创建Element类型的vector、填充数据并传入foo:
std::vector<Element> es; // resize仅用于分配内存,所有值后续会在并行区域重写 es.resize( N ); // 并行计算vector中所有值以获得最佳性能 tbb::parallel_for( tbb::blocked_range<size_t>( 0, es.size() ), [&]( const tbb::blocked_range<size_t> & range ) { for ( size_t i = range.begin(); i < range.end(); ++i ) { ... es[i] = ... } } ); … foo( es );
我发现当N很大时,es.resize会消耗大量时间,因为它不仅分配内存,还会默认初始化每个元素,而这在我的场景中完全没必要。
是否存在一种无需初始化元素即可增大vector大小的方法?类似std::make_unique_for_overwrite的功能。
解决方案
C++20及以上版本(推荐)
直接使用C++20新增的std::vector::resize_default_init方法,它专门用于这种「只分配内存、跳过默认初始化」的场景:
std::vector<Element> es; es.resize_default_init(N); // 仅分配内存,不初始化元素
这个函数会将vector的大小调整为N,但不会对新元素执行默认构造,恰好匹配你的需求——后续并行计算会完全覆盖所有元素,无需提前初始化。
C++20之前的版本
由于标准库没有直接提供对应功能,可通过以下技巧间接实现,但需注意代码安全性:
- 先调用
reserve(N)预留足够内存 - 使用分配器在预留的内存中构造元素时,绕过默认构造(但这依赖于编译器和平台,且对于非平凡类型存在风险)
不过更稳妥的替代方案是:如果无法升级到C20,可临时使用std::vector<char>分配内存后,通过reinterpret_cast转为Element*操作,但注意不能直接将这个vector传给foo,需要额外构造std::vector<Element>并移动内存(这会抵消部分性能收益),因此优先推荐升级到C20使用官方方案。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

