c++ 为什么我的基本Vector实现比stl版本的push_back要快?

nwwlzxa7  于 2023-01-28  发布在  其他
关注(0)|答案(2)|浏览(199)

我已经使用韦斯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';

    
    
}
myzjeezk

myzjeezk1#

您在调试中编译了它。
在调试中,visual studio用一堆调试辅助工具来检测std::vector。例如,在某些情况下,如果你试图使用无效的迭代器,它会检测到。
一般来说,在debug中做性能测试是没有用的。你应该做的唯一原因是你遇到了问题,你的调试构建太慢了,不适合开发。
应用程序的真实的使用应该在发布模式下完成,这样可以进行优化,也可以消除额外的“双重检查”工作来帮助查找bug。
你的向量确实不同了,但这种不同并不重要。

dauxcl2d

dauxcl2d2#

您的矢量实现和std::vector有根本的不同。
您的vector default-constructing向量中的所有值,直到保留容量,而push_back()只是使用赋值运算符用新值替换下一个保留值。
std::vector与,有根本的不同,它不会默认构造向量中“不存在”的值,而是构造“真实”的值。std::vector::push_back在向量中构造新值,您的push_back将对其进行赋值。
根据容器中的对象,其赋值运算符和构造函数可能具有完全不同的逻辑,比较基准没有意义。

相关问题