在 C++ 中制作自己的向量时如何处理垃圾值?

how to handle garbage value while making my own vector in c++?

大家晚上好 我正在尝试制作自己的矢量 class。 但我几乎没有问题。 首先,我不知道为什么有垃圾值 我试图检查构造函数,但找不到原因。

例如,如果我尝试制作

Vector<int> arr1(5);

Vector<int> ::iterator it;
arr1.push_front(1);
arr1.push_back(2);
arr1.push_back(3);
arr1.push_back(4);
arr1.push_back(5);

for (it = arr1.begin(); it != arr1.end(); it++)
    cout << *it;

结果是 1-842150451-842150451-842150451-842150451-8421504512345

其次,我想做 Insert(firstPostion,secondPosition) 但是我不知道怎么做。 请帮助我谢谢。 我添加了 vector.h 和 main.cpp

#ifndef VECTOR_H
#define VECTOR_H

#include <algorithm>
#include <iostream>
#include <stdexcept>
#include "dsexceptions.h"

template <typename Object>
class Vector
{
public:
    explicit Vector(int initSize = 0)
        : theSize( initSize ), theCapacity( initSize + SPARE_CAPACITY )
    { objects = new Object[theCapacity]; }

    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];
    }

    Vector& operator= (const Vector& rhs)
    {
        Vector copy = rhs;
        std::swap(*this, copy);
        return *this;
    }

    ~Vector()
    {
        delete[] objects;
    }

    Vector(Vector&& rhs)
        : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects }
    {
        rhs.objects = nullptr;
        rhs.theSize = 0;
        rhs.theCapacity = 0;
    }

    Vector& operator= (Vector&& rhs)
    {
        std::swap(theSize, rhs.theSize);
        std::swap(theCapacity, rhs.theCapacity);
        std::swap(objects, rhs.objects);

        return *this;
    }

    bool empty() const
    {
        return size() == 0;
    }
    int size() const
    {
        return theSize;
    }
    int capacity() const
    {
        return theCapacity;
    }

    Object& operator[](int index)
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw ArrayIndexOutOfBoundsException{ };
#endif
        return objects[index];
    }

    const Object& operator[](int index) const
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw ArrayIndexOutOfBoundsException{ };
#endif
        return objects[index];
    }

    void resize(int newSize)
    {
        if (newSize > theCapacity)
            reserve(newSize * 2);
        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;
    }

    // Stacky stuff
    void push_back(const Object& x)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[theSize++] = x;
    }
    // Stacky stuff
    void push_back(Object&& x)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[theSize++] = std::move(x);
    }

    void pop_back()
    {
        if (empty())
            throw UnderflowException{ };
        --theSize;
    }

    const Object& back() const
    {
        if (empty())
            throw UnderflowException{ };
        return objects[theSize - 1];
    }

    // Iterator stuff: not bounds checked
    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 = 2;

    /*************************************************************************/
    /*************************************************************************/

    iterator insert(const_iterator position, const Object& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity + 1);
        }
        int index = position - objects;
        for (int i = theSize - 1; i >= index; --i)
            objects[i + 1] = objects[i];
        objects[index] = val;
        theSize++;

        return &objects;
        
    }

    iterator insert(const_iterator position, Object&& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity + 1);
        }
        int index = position - objects;
        for (int i = theSize-1; i>=index; --i)
            objects[i+1] = objects[i];
        objects[index] = std::move(val);
        theSize++;

        return objects;
    }

    
    template <class InputIterator>
    iterator insert(const_iterator position, InputIterator first, InputIterator last)
    {
        
        
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity + 1);
        }
        Object* newObjects = last - first;
        


        

        return &objects;
    }

    
    iterator erase(const_iterator position)
    {
        theSize--;
        int index = position - begin();
        
        Object* newObj = new Object[theCapacity];
        for (int i = 0, j = 0; j <= theSize; ++j)
        {
            if (j != index)
                newObj[i++] = objects[j];
        }
        delete[] objects;

        objects = newObj;
        

        return &objects[index];
    }

    
    iterator erase(const_iterator first, const_iterator last)
    {
        int index = last - first;
        theSize = index;
        Object* Array = new Object[theCapacity];
        for (int i = 0; i <= index; i++)
            Array[i] = objects[i + index];

        return Array;
    }


    
    void push_front(const Object& val)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[0] = val;
        theSize++;
    }

    void push_front(Object&& val)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[0] = std::move(val);
        theSize++;
        
    }

    
    Object& front()
    {
        if (empty())
            throw UnderflowException{};
        return objects[0];
        
    }

    const Object& front() const
    {
        if (empty())
            throw UnderflowException{ };
        return objects[0];
    }

    /*************************************************************************/
    /*************************************************************************/



  private:
    int theSize;
    int theCapacity;
    Object * objects;
};

#endif


#include "Vector.h"
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    Vector<int> arr1(5);
    Vector<int> arr2(5);
    Vector<int> ::iterator it;
    arr1.push_front(1);
    arr1.push_back(2);
    arr1.push_back(3);
    arr1.push_back(4);
    arr1.push_back(5);
    arr1.erase(arr1.begin(), arr1.begin() + 2);
    for (it = arr1.begin(); it != arr1.end(); it++)
        cout << *it;
    cout << endl;
    cout << arr1.size();
    
    
    
       

  


    return 0;
}

很多很多误会。

你的范围插入和擦除很奇怪。还有一些其他的错误。

请注意,如果您在 C++ 中使用范围,则范围的 end() 始终必须指向范围中最后一个元素之后的一个。

请注意我在您的代码中添加的注释。 我还用 std::exceptions 替换了所有异常,以便我可以编译。

关于您看到的不确定值。

如果创建大小为 5 的 Vector,则这 5 个值最初是不确定的。也许您想“保留”5 个字节?

但是现在你有 5 个字节了。如果您使用 push_back,那么新值将添加到 5 个初始元素之后。作为元素索引 5,6,7,8 等等。

请阅读 CPP 参考中 std::vector 中的 API。

请查看您的注释代码:

#include <iostream>
#include <algorithm>
#include <stdexcept>

template <typename Object>
class Vector
{
public:
    explicit Vector(int initSize = 0)                             
        : theSize(initSize), theCapacity(initSize + SPARE_CAPACITY)
    {
        objects = new Object[theCapacity];
    }

    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];
    }

    Vector& operator= (const Vector& rhs)
    {
        Vector copy = rhs;          // Bug! Self Calling
        std::swap(*this, copy);     // Bug: Do not swap, you want to assign and both sould contain the same values
        return *this;
    }

    ~Vector()
    {
        delete[] objects;
    }

    Vector(Vector&& rhs)
        : theSize{ rhs.theSize }, theCapacity{ rhs.theCapacity }, objects{ rhs.objects }
    {
        rhs.objects = nullptr;      // If this contains elements, then delete them
        rhs.theSize = 0;
        rhs.theCapacity = 0;
    }

    Vector& operator= (Vector&& rhs)
    {
                                                    // Delete old contents of this
        std::swap(theSize, rhs.theSize);            // Do not swap!!!  Move, like in the move assignment operator
        std::swap(theCapacity, rhs.theCapacity);
        std::swap(objects, rhs.objects);

        return *this;
    }

    bool empty() const
    {
        return size() == 0;
    }
    int size() const
    {
        return theSize;
    }
    int capacity() const
    {
        return theCapacity;
    }

    Object& operator[](int index)
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw std::out_of_range;
#endif
        return objects[index];
    }

    const Object& operator[](int index) const
    {
#ifndef NO_CHECK
        if (index < 0 || index >= size())
            throw std::out_of_range;
#endif
        return objects[index];
    }

    void resize(int newSize)
    {
        if (newSize > theCapacity)  // Bug: Should be >=
            reserve(newSize * 2);
        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);  // Will work, but why always swapping? Assignment is sufficient
        delete[] newArray;
    }

    // Stacky stuff
    void push_back(const Object& x)
    {
        if (theSize == theCapacity)       // Just for safety: Should be >=
            reserve(2 * theCapacity + 1); // 2* the capacity should always be sufficient
        objects[theSize++] = x;
    }
    // Stacky stuff
    void push_back(Object&& x)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[theSize++] = std::move(x);
    }

    void pop_back()
    {
        if (empty())
            throw std::underflow_error;
        --theSize;
    }

    const Object& back() const
    {
        if (empty())
            throw std::underflow_error;
        return objects[theSize - 1];
    }

    // Iterator stuff: not bounds checked
    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 = 2;

    /*************************************************************************/
    /*************************************************************************/

    iterator insert(const_iterator position, const Object& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity + 1);
        }

        int index = position - objects;
        for (int i = theSize - 1; i >= index; --i)
            objects[i + 1] = objects[i];
        objects[index] = val;

        theSize++;

        return &objects;

    }

    iterator insert(const_iterator position, Object&& val)
    {
        if (theSize == theCapacity)
        {
            reserve(2 * theCapacity + 1);
        }
        int index = position - objects;
        for (int i = theSize - 1; i >= index; --i)
            objects[i + 1] = objects[i];
        objects[index] = std::move(val);
        theSize++;

        return objects;
    }


    template <class InputIterator>
    iterator insert(const_iterator position, InputIterator first, InputIterator last)
    {
        if (theSize == theCapacity)         // Bug, completely wrong. Now insertion
        {
            reserve(2 * theCapacity + 1);
        }
        Object* newObjects = last - first;  

        return &objects;
    }


    iterator erase(const_iterator position)
    {
        theSize--;
        int index = position - begin();     

        Object* newObj = new Object[theCapacity];       // Strange algorithm. Why copy all data instead of shifting
        for (int i = 0, j = 0; j <= theSize; ++j)
        {
            if (j != index)
                newObj[i++] = objects[j];
        }
        delete[] objects;

        objects = newObj;


        return &objects[index];
    }


    iterator erase(const_iterator first, const_iterator last)
    {
        int index = last - first;
        theSize = index;            // Wrong and too comlicated
        Object* Array = new Object[theCapacity];
        for (int i = 0; i <= index; i++)     // Wrong
            Array[i] = objects[i + index];   // 

        return Array;
    }

    void push_front(const Object& val)
    {
        if (theSize == theCapacity)
            reserve(2 * theCapacity + 1);
        objects[0] = val;       // Bug. Just overwriting. No push front
        theSize++;              // No last value will be indeterminate
    }

    void push_front(Object&& val)
    {
        if (theSize == theCapacity)     // Bug. See above
            reserve(2 * theCapacity + 1);
        objects[0] = std::move(val);
        theSize++;

    }

    Object& front()
    {
        if (empty())
            throw std::underflow_error;
        return objects[0];

    }

    const Object& front() const
    {
        if (empty())
            throw std::underflow_error;
        return objects[0];
    }
    /*************************************************************************/
    /*************************************************************************/
private:
    int theSize;
    int theCapacity;
    Object* objects;
};

int main()
{
    Vector<int> arr1(5);            // Creating a vector arr1 with 5 indeterminate elements
    Vector<int> arr2(5);            // Creating a vector arr1 with 5 indeterminate elements
    Vector<int> ::iterator it;
    arr1.push_front(1);             // Will set aissign one to the first element
    arr1.push_back(2);              // Will add a new element at the end. So, now first element has value, 2nd,3rd, 4th and 5th are indeterminate. Last will be 2
    arr1.push_back(3);              // See above
    arr1.push_back(4);              // See above
    arr1.push_back(5);              // See above
    arr1.erase(arr1.begin(), arr1.begin() + 2);         // Does not work correctly
    for (it = arr1.begin(); it != arr1.end(); it++)     // Will just show 2 values
        std::cout << *it;
    std::cout << '\n';
    std::cout << arr1.size();
    return 0;
}