#// SimpleVector class template
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <new> // Needed for bad_alloc exception
#include <cstdlib> // Needed for the exit function
usingnamespace std;
template <class T>
class SimpleVector
{
private:
T *aptr; // To point to the allocated array
int arraySize; // Number of elements in the array
void memError(); // Handles memory allocation errors
void subError(); // Handles subscripts out of range
public:
// Default constructor
SimpleVector()
{
aptr = 0; arraySize = 0;
}
// Constructor declaration
SimpleVector(int);
// Copy constructor declaration
SimpleVector(const SimpleVector &);
// Destructor declaration
~SimpleVector();
// Accessor to return the array size
int size() const
{
return arraySize;
}
// Accessor to return a specific element
T getElementAt(int position);
// Overloaded [] operator declaration
T &operator[](constint &);
// new functions
void push_back(T); // New push_back member
T pop_back(); // New pop_back member
};
//***********************************************************
// Constructor for SimpleVector class. Sets the size of the *
// array and allocates memory for it. *
//***********************************************************
template <class T>
SimpleVector<T>::SimpleVector(int s)
{
arraySize = s;
// Allocate memory for the array.
try
{
aptr = new T[s];
}
catch (bad_alloc)
{
memError();
}
// Initialize the array.
for (int count = 0; count < arraySize; count++)
*(aptr + count) = 0;
}
//*******************************************
// Copy Constructor for SimpleVector class. *
//*******************************************
template <class T>
SimpleVector<T>::SimpleVector(const SimpleVector &obj)
{
// Copy the array size.
arraySize = obj.arraySize;
// Allocate memory for the array.
aptr = new T[arraySize];
if (aptr == 0)
memError();
// Copy the elements of obj's array.
for (int count = 0; count < arraySize; count++)
*(aptr + count) = *(obj.aptr + count);
}
//**************************************
// Destructor for SimpleVector class. *
//**************************************
template <class T>
SimpleVector<T>::~SimpleVector()
{
if (arraySize > 0)
delete[] aptr;
}
//*******************************************************
// memError function. Displays an error message and *
// terminates the program when memory allocation fails. *
//*******************************************************
template <class T>
void SimpleVector<T>::memError()
{
cout << "ERROR:Cannot allocate memory.\n";
exit(EXIT_FAILURE);
}
//***********************************************************
// subError function. Displays an error message and *
// terminates the program when a subscript is out of range. *
//***********************************************************
template <class T>
void SimpleVector<T>::subError()
{
cout << "ERROR: Subscript out of range.\n";
exit(EXIT_FAILURE);
}
//*******************************************************
// getElementAt function. The argument is a subscript. *
// This function returns the value stored at the sub- *
// cript in the array. *
//*******************************************************
template <class T>
T SimpleVector<T>::getElementAt(int sub)
{
if (sub < 0 || sub >= arraySize)
subError();
return aptr[sub];
}
//*******************************************************
// Overloaded [] operator. The argument is a subscript. *
// This function returns a reference to the element *
// in the array indexed by the subscript. *
//*******************************************************
template <class T>
T &SimpleVector<T>::operator[](constint &sub)
{
if (sub < 0 || sub >= arraySize)
subError();
return aptr[sub];
}
// new functions
//***********************************************************
// The push_back function pushes its argument onto the back *
// of the vector. *
//***********************************************************
template <class T>
void SimpleVector<T>::push_back(T)
{
// Allocate a new array 1 element larger than the current one.
new temp = new T[arraySize + 1];
// Copy the current array contents to the new array
for (int index = 0; index < arraySize; index++)
{
temp[index] = aptr[index];
}
// Copy the argument value to the end of the array
temp[arraySize-1] = T;
// Delete the old array (aptr)
delete[] aptr;
// Make aptr point to the new array
aptr = temp;
// Adjust arraySize to reflect the extra element you just added
arraySize++;
}
//***********************************************************
// The pop_back function removes the last element *
// of the vector. It also returns that value. *
//***********************************************************
template <class T>
T SimpleVector<T>::pop_back()
{
if(arraySize == 0 || aptr == NULL)
{
std::cout<<"cannot pop back! \n";
return;
}
Type* temp = new Type[arraySize];
for(int index = 0; index < arraySize; index++)
{
temp[index] = aptr[index];
}
temp[arraySize--];
delete [] aptr;
aptr = temp;
}
// Save the last value in the array
// Allocate a new array 1 element smaller than the current one.
// Copy the current array contents (except the last element)
// to the new array
// Delete the old array (aptr)
// Make aptr point to the new array
// Adjust arraySize to reflect the extra element you just removed
// return the last value of the old array
#endif
template <class T>
void SimpleVector<T>::push_back(T t)
{
// Allocate a new array 1 element larger than the current one.
T *temp = new T[arraySize++];
// Copy the current array contents to the new array
for (int index = 0; index < arraySize; index++)
{
temp[index] = aptr[index];
}
// Copy the argument value to the end of the array
temp[arraySize++] = t;
// Delete the old array (aptr)
delete[] aptr;
// Make aptr point to the new array
aptr = temp;
// Adjust arraySize to reflect the extra element you just added
arraySize++;
}
//***********************************************************
// The pop_back function removes the last element *
// of the vector. It also returns that value. *
//***********************************************************
template <class T>
T SimpleVector<T>::pop_back()
{
//if (arraySize == 0 || aptr == NULL)
//{
// std::cout << "cannot pop back! \n";
// return;
//}
//T* temp = new T[arraySize];
//for (int index = 0; index < arraySize; index++)
//{
// temp[index] = aptr[index];
//}
//temp[arraySize--];
//delete[] aptr;
//aptr = temp;
// Save the last value in the array
T temp = aptr[arraySize - 1];
// Allocate a new array 1 element smaller than the current one.
T* temp2 = new T[arraySize - 1];
// Copy the current array contents (except the last element)
// to the new array
for (int i = 0; i < arraySize - 1; i++)
{
temp2[i] = aptr[i];
}
// Delete the old array (aptr)
delete[] aptr;
// Make aptr point to the new array
aptr = temp2;
// Adjust arraySize to reflect the extra element you just removed
arraySize = arraySize - 1;
// return the last value of the old array
return temp;
}
#endif
THis is what i came up with so far. I am getting an extra value at the end after the push_back(int) is executed in main. not sure why
// Allocate a new array 1 element larger than the current one.
T *temp = new T[arraySize++];
1 2
// Copy the argument value to the end of the array
temp[arraySize++] = t;
I wouldn't trust this...
Take a look here - the following code on my machine results in me accessing out-of-bounds memory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
int main() {
int size = 2;
int* ptr = newint[size++] {0};//array with three elements, right?
for (int i = 0; i < size; ++i) {
std::cout << "ptr[" << i << "]: " << ptr[i] << std::endl;
}
delete[] ptr;
ptr = nullptr;
std::cin.ignore();
return 0;
}
ptr[0]: 0
ptr[1]: 0
ptr[2]: -33686019
The reason for this is because the postfix operator (in my case 'size++', in your case 'arraySize++') only increments the parameter after the expression has already taken the original value of 'size' or 'arraySize'.
This can be fixed with the prefix alternative:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <iostream>
int main() {
int size = 2;
int* ptr = newint[++size] {0};//There we go
for (int i = 0; i < size; ++i) {
std::cout << "ptr[" << i << "]: " << ptr[i] << std::endl;
}
delete[] ptr;
ptr = nullptr;
std::cin.ignore();
return 0;
}
ptr[0]: 0
ptr[1]: 0
ptr[2]: 0
I doubt this is the cause for your additional undesired element at the end of your vector - I haven't really taken a close look - this just stuck out to me.
I think i was wrong in saying an additional element. It is probably an access to out of bounds memory as you said. However, I have tried the prefix alternative and I get heap error. I have never seen this so I will research this now.
template <class T>
void SimpleVector<T>::push_back(T t)
{
// Allocate a new array 1 element larger than the current one.
T* temp;
temp = new T[++arraySize];
arraySize--;
// Copy the current array contents to the new array
for (int index = 0; index < arraySize; index++)
{
temp[index] = aptr[index];
}
// Copy the argument value to the end of the array
temp[arraySize++] = t;
// Delete the old array (aptr)
delete[] aptr;
// Make aptr point to the new array
aptr = temp;
// Adjust arraySize to reflect the extra element you just added
arraySize;
}
This is what i came up with. I know its not the best solution but its the only way I could get the thing to run.