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;
}
CodePudding user response:
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;
}