为何自行实现的简易Vector的push_back性能优于STL版本?
为什么自定义Vector的push_back比std::vector快8倍?
我基于Weiss的C++数据结构教材实现了一个简易Vector类,在执行100000次push_back操作时耗时0.001秒;而使用std::vector执行完全相同的测试时,耗时0.008秒,速度约慢8倍。请问造成这种差异的原因是什么?
#include <iostream> #include <algorithm> #include <ctime> #include <vector> template<typename Object> class Vector { public: // normal constructor explicit Vector(int initialSize = 0) : theSize{ initialSize }, theCapacity{ initialSize + SPARE_CAPACITY }, objects{ new Object[theCapacity] } {} // copy constructor Vector(const Vector& rhs) : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ nullptr } { objects = new Object[theCapacity]; for (int k = 0; k < theSize; ++k) objects[k] = rhs.objects[k]; } // copy assignment operator Vector& operator=(const Vector& rhs) { Vector copy = rhs; std::swap(*this, copy); return *this; } // destructor ~Vector() { delete[] objects; } // move constructor Vector(Vector&& rhs) : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects } { rhs.objects = nullptr; rhs.theSize = 0; rhs.theCapacity = 0; } // move assignment operator Vector& operator=(Vector&& rhs) { std::swap(theSize, rhs.theSize); std::swap(theCapacity, rhs.theCapacity); std::swap(objects, rhs.objects); return *this; } void resize(int newSize) { if (newSize > theCapacity) reserve(newSize * 2); // talk about amortized time (python book) theSize = newSize; } void reserve(int newCapacity) { if (newCapacity < theSize) return; Object* newArray = new Object[newCapacity]; for (int k = 0; k < theSize; ++k) newArray[k] = std::move(objects[k]); theCapacity = newCapacity; std::swap(objects, newArray); delete[] newArray; } Object& operator[](int index) { return objects[index]; } const Object& operator[](int index)const { return objects[index]; } bool empty() const { return size() == 0; } int size() const { return theSize; } int capacity() const { return theCapacity; } void push_back(const Object& x) { if (theSize == theCapacity) reserve(2 * theCapacity + 1); objects[theSize++] = x; } void push_back(Object&& x) { if (theSize == theCapacity) reserve(2 * theCapacity + 1); objects[theSize++] = std::move(x); } void pop_back() { --theSize; } const Object& back() const { return objects[theSize - 1]; } // iterator typedef Object* iterator; typedef const Object* const_iterator; iterator begin() { return &objects[0]; } const_iterator begin() const { return &objects[0]; } iterator end() { return &objects[size()]; } const_iterator end() const { return &objects[size()]; } static const int SPARE_CAPACITY = 16; private: int theSize; int theCapacity; Object* objects; }; int main() { std::clock_t start; start = std::clock(); std::vector<int> vec2{ 0 }; for (int i = 0; i < 100000; i++) vec2.push_back(i); double duration = (std::clock() - start) / (double)CLOCKS_PER_SEC; std::cout << "printf: " << duration << '\n'; start = std::clock(); Vector<int> vec{ 0 }; for (int i = 0; i < 100000; i++) vec.push_back(i); duration = (std::clock() - start) / (double)CLOCKS_PER_SEC; std::cout << "printf: " << duration << '\n'; }
核心原因分析
1. 测试流程的系统性偏差
- 缓存预热效应:你先测试
std::vector再测试自定义Vector,第一次测试会触发内存页分配、CPU缓存加载等系统级开销,第二次测试时这些资源已经就绪,自然速度更快。交换两次测试顺序,结果很可能反转。 - 时钟精度限制:
std::clock()的精度有限,对于仅耗时几毫秒的操作,测量结果容易出现较大误差,单次测试的参考价值很低。
2. 实现细节的差异
- 调试模式额外开销:如果测试是在Debug编译模式下进行,
std::vector会包含大量调试检查(比如边界越界检测、迭代器有效性验证、内存填充哨兵值等),这些都是自定义Vector没有的额外开销,会显著拖慢速度。Release模式下这些检查会被移除。 - 扩容策略与次数:自定义
Vector初始容量为16(SPARE_CAPACITY=16),扩容公式是2*capacity+1;而std::vector的初始容量和扩容策略依赖具体实现,比如很多实现初始容量从1开始,每次扩容翻倍。对于100000次push_back,std::vector的扩容次数会比自定义Vector多,每次扩容的内存拷贝开销累积起来会形成差距。 - 内存分配器的复杂度:
std::vector使用标准分配器std::allocator,其实现会考虑内存对齐、线程安全、内存池兼容等通用场景,相比自定义Vector直接用new[]的简单分配,会有额外的逻辑开销。 - 编译器优化空间:自定义
Vector的代码逻辑更简洁直白,编译器更容易进行深度优化;而std::vector作为标准库组件,代码包含更多通用兼容逻辑,编译器优化的难度更高,尤其是在未开启最高优化等级时。
3. 测试严谨性不足
单次测试的结果受环境影响极大,正确的测试方式应该:
- 开启最高等级优化(如
-O3) - 交换测试顺序,多次测试取平均值
- 控制变量,确保两个容器的初始状态完全一致(比如都从空容器开始测试,而非初始包含一个元素)
内容的提问来源于stack exchange,提问作者Russell Butler
相关产品推荐
相关产品推荐

