简体   繁体   中英

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

Good evening guys I am trying to make my own vector class. But I have few problems. Firstable, I dont know why There is garbage value I've tried to check constructor but I couldn't find reason.

For example If i tried to make

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;

the result is 1-842150451-842150451-842150451-842150451-8421504512345

Second, I want to make Insert(firstPostion,secondPosition) But I dont know how to make. Plz help me Thanks. I added my vector.h and 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;
}

Many many misunderstanding.

Your range insert and erase is more than strange. There are some other bugs.

Please not, if you work with ranges in C++, then the end() of the range always has to point to one past the last element in the range.

Please the the comments that I put in your code. I also replace all exceptions with std::exceptions so that I can compile.

Regarding the indeterminate values that you see.

If you create an Vector having the size 5, then these 5 values are initially indeterminate. Maybe you want to "reserve" 5 bytes?

But now you have the 5 bytes. And if you use push_back then the new values will be added after the 5 initial elements. As element index 5,6,7,8 and so on.

Please read about the API from std::vector in CPP Reference.

Please see your annotated code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM