如何在C++中高效填充vector并优化数值赋值函数的性能?
首先得指出,你第一个实现有严重问题:构造vector时已经分配了elementCount大小的空间并默认初始化所有元素为0,之后调用push_back会把元素追加到现有空间后面,最终vector的大小会变成2*elementCount,完全不符合需求,还做了多余的内存分配和初始化操作,性能极差,直接废弃就行。
你的第二个实现已经修正了逻辑问题,性能比第一个好很多,但还有优化空间,下面是几个更优的方案:
1. 避免多余的默认初始化
第二个实现里std::vector<uint64_t> vec(elementCount);会先把所有元素默认初始化为0,之后你又赋值为i,这多了一轮不必要的内存写入。改用reserve预留空间+emplace_back直接构造元素,就能跳过默认初始化步骤:
std::vector<uint64_t> fill_vector(size_t elementCount) { std::vector<uint64_t> vec; vec.reserve(elementCount); for (size_t i = 0; i < elementCount; ++i) { vec.emplace_back(i); } return vec; }
这样vector只分配一次内存,直接在预留空间里构造元素,少了一轮全量内存写入,性能会比第二个实现更优。
2. 用C++20的视图简化实现(性能拉满)
如果你的项目支持C++20,直接用std::views::iota生成连续整数序列,再转换为vector即可。标准库的实现通常经过高度优化,编译器能做更多底层优化(比如向量化、循环展开),性能大概率比手写循环更好:
#include <ranges> std::vector<uint64_t> fill_vector(size_t elementCount) { return std::vector<uint64_t>(std::views::iota(0ULL, elementCount)); }
这个写法还极度简洁,可读性拉满。
3. 编译器优化必不可少
不管用哪种实现,一定要开启编译器的最高级优化(比如GCC/Clang的-O3,MSVC的/O2)。编译器会自动对循环做向量化、循环展开、消除冗余操作等优化,这对性能的提升往往比代码层面的小改动更显著。
极端场景的手动优化(不推荐)
如果追求极致性能且能接受代码复杂度提升,可以直接操作内存构造元素,跳过vector的部分封装逻辑,但这种方式容易出错,只建议在极端性能敏感场景使用:
#include <memory> std::vector<uint64_t> fill_vector(size_t elementCount) { std::vector<uint64_t> vec; vec.reserve(elementCount); uint64_t* data = vec.data(); for (size_t i = 0; i < elementCount; ++i) { std::construct_at(data + i, i); vec.push_back(std::move(*(data + i))); } return vec; }
不过实际上,emplace_back已经封装了类似逻辑,大部分场景下没必要这么写。
内容的提问来源于stack exchange,提问作者Lihi Sabag

