我已经使用韦斯C++教科书中关于数据结构的代码实现了一个基本的向量(见下文)。当我用100,000次push_backs计时时,需要0.001秒。
当我用stl::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';
}
2条答案
按热度按时间myzjeezk1#
您在调试中编译了它。
在调试中,visual studio用一堆调试辅助工具来检测std::vector。例如,在某些情况下,如果你试图使用无效的迭代器,它会检测到。
一般来说,在debug中做性能测试是没有用的。你应该做的唯一原因是你遇到了问题,你的调试构建太慢了,不适合开发。
应用程序的真实的使用应该在发布模式下完成,这样可以进行优化,也可以消除额外的“双重检查”工作来帮助查找bug。
你的向量确实不同了,但这种不同并不重要。
dauxcl2d2#
您的矢量实现和
std::vector
有根本的不同。您的vector default-constructing向量中的所有值,直到保留容量,而
push_back()
只是使用赋值运算符用新值替换下一个保留值。std::vector
与,有根本的不同,它不会默认构造向量中“不存在”的值,而是构造“真实”的值。std::vector::push_back
在向量中构造新值,您的push_back
将对其进行赋值。根据容器中的对象,其赋值运算符和构造函数可能具有完全不同的逻辑,比较基准没有意义。