Creating a "push_back" Function for Array - c++

My assignment is to create push_back and pop_back functions for a SimpleVector which have to do basically what you imagine they have to do. I'm trying to add an element to an existing array in this fashion but it isn't working. It adds 0 instead of the number I pass in in main. Any ideas as to why?
SimpleVector.h
// 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
using namespace 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[](const int &);
void push_back(SimpleVector, int);
void pop_back(SimpleVector, int);
};
//***********************************************************
// 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- *
// script 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[](const int &sub)
{
if (sub < 0 || sub >= arraySize)
subError();
return aptr[sub];
}
#endif
template<class T>
void SimpleVector<T>::push_back(SimpleVector obj, int newval)
{
arraySize = obj.arraySize + 1;
// 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 - 1); count++)
*(aptr + count) = *(obj.aptr + count);
obj.aptr[(arraySize)] = newval;
}
main.cpp
// This program demonstrates the SimpleVector template.
#include <iostream>
#include "SimpleVector.h"
using namespace std;
int main()
{
const int SIZE = 10; // Number of elements
int amtToPrnt = 10;
int count; // Loop counter
// Create a SimpleVector of ints.
SimpleVector<int> intTable(SIZE);
// Store values in the two SimpleVectors.
for (count = 0; count < SIZE; count++)
{
intTable[count] = (count * 2);
}
// Display the values in the SimpleVectors.
cout << "These values are in intTable:\n";
for (count = 0; count < amtToPrnt; count++)
cout << intTable[count] << " ";
cout << endl;
intTable.push_back(intTable, 20);
cout << "These values are in intTable after adding one more value:\n";
for (count = 0; count < ++amtToPrnt; count++)
cout << intTable[count] << " ";
cout << endl;
/*
intTable.push_back(intTable, 22);
cout << "These values are in intTable after adding one more value:\n";
for (count = 0; count < ++amtToPrnt; count++)
cout << intTable[count] << " ";
cout << endl;
intTable.push_back(intTable, 24);
cout << "These values are in intTable after adding one more value:\n";
for (count = 0; count < ++amtToPrnt; count++)
cout << intTable[count] << " ";
cout << endl;
*/
return 0;
}

SimpleVector.h
void push_back(int);
I remove SimpleVector to reduce memory usage.
template <class T>
void SimpleVector<T>::push_back(int newval){
// Allocate memory for the array in the temporary array.
T * tmpArray = new T [arraySize + 1];
// Copy the elements of old array.
for(int count = 0; count < arraySize; count++)
*(tmpArray + count) = *(aptr + count);
// Push new value
*(tmpArray + arraySize) = newval;
// Delete old array
delete[] aptr;
// Copy array
aptr = tmpArray;
// Increase size
arraySize++;
}
main.cpp
intTable.push_back(20);
amtToPrnt++;
cout << "These values are in intTable after adding one more value:\n";
for (count = 0; count < amtToPrnt; count++)
cout << intTable[count] << " ";
cout << endl;
Result :
Side note:
You should refactor your SimpleVector. Don't use pass by value if you didn't need it. And I suggest to made the arraySize public to know how many data are in your vector.

SimpleVector<T>::push_backis a bit of a wreck. Let's take a look, shall we?
void SimpleVector<T>::push_back(SimpleVector obj, int newval)
SimpleVector obj is passed by value, so the obj operated on is a copy. Recommend passing by reference. But why do this in the first place? What use is a push_back that pushes back a SimpleVector AND a new value? Recommend rethinking this approach.
{
arraySize = obj.arraySize + 1;
// Allocate memory for the array.
aptr = new T[arraySize];
OK. That's all good. Except, what if aptr already pointed at memory? You'd have to delete[] that first, but then what would you copy? Recommend working with a temporary variable here and assigning the temporary after the copying and deleting is finished.
if (aptr == 0)
memError();
This will never happen. new throws bad_alloc on allocation errors so the program will never get here if new failed. Earlier the program did this:
try
{
aptr = new T[s];
}
catch (bad_alloc)
{
memError();
}
It's very likely you want to do it again.
It is also bad form to use 0 in place of nullptr. 0 is a magic number AND it's not a pointer.
// Copy the elements of obj's array.
for (int count = 0; count < (arraySize - 1); count++)
*(aptr + count) = *(obj.aptr + count);
All groovy. Nothing to see here other than clunky-looking pointer arithmetic where aptr[count] would have sufficed. However as outlined above, this is unexpected behaviour for a push_back function.
obj.aptr[(arraySize)] = newval;
obj is still obj.arraySize sized and arraySize is one bigger. Next, the array is indexed 0..obj.arraySize-1, so this writes not one, but two elements past the end of the array and invokes undefined behaviour. Who knows what will result from doing this? I sure don't.
Next, it modifies obj which is a copy that is about to be destroyed. I suspect *(aptr + arraySize - 1) = newval; would be more useful.
}
While I was writing this a perfectly serviceable what to do answer went up. Refer to it.
Optimization: Instead of always increasing by 1, why not save yourself a lot of resizing and copying and increase the size by a factor of two?

When you call push_back, the first parameter is passed by value. In other words, a temporary copy is created. Then you allocate a new array (without deleting the original - memory leak!) and change the ptr in this to the new array. Fine, but then you put the new value into the temporary vector, which is destroyed after returning from the function.

Related

C++: what if we don't allocate an object with new, but the class itself contains a new in constructor?

Hope my question isn't confusing. I'll explain that with code.
I'm learning constructor/desctructor and new/delete in C++. While comparing two piece of code, I'm thinking about where the object and it's members are allocated.
I got a little bit confused when I see the new in constructor and main, and delete in destructor and main:
In the first example, I think local object c is allocated in stack. And that means, members list pointer, two int values (size and capacity) are all in stack. The object also contains an array in size 10, however the array itself is allocated in heap since new is used. When the program ends, the local object c (including the pointer) will be freed automatically. And the array pointed by pointer list will be freed as well, by destructor. Is that correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector c(10);
for (int i = 0 ; i < 15 ; i++){
cout << c.append(i) << endl;
}
}
Now compared with the second example, object is created with new. So all members including pointer and two int values are all allocated from heap. The array itself is also in heap for the same reason as the first example. Before the program ends, there is a delete so the pointer and two int values are all freed. The array is also freed since the desctructor is called when delete command is issued. Is my understanding correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector *c;
c = new Collector(10);
for (int i = 0 ; i < 15 ; i++){
cout << c->append(i) << endl;
}
delete c;
cout << "Exiting program" << endl;
}

Creating a custom Vector class errors

So I am trying to create a custom class that functions like a vector. It is supposed to have a default constructor that creates an empty vector with a capacity of 2, a parameterized constructor with a capacity of n, a destructor, a function to return the size of a vector, the capacity of a vector, a function to delete the data and reset a vector to capacity 2, a push_back function to put n at the end of a vector, and a function to return the value stored at n. I have the majority of the code written out, but I am receiving errors on the driver.cpp file whenever I try to use the .capacity() function to show the capacity of the "vector". Errors are
too few arguments in function call' and Vector::capacity: function
does not take 0 arguments
every time I try to use capacity() in driver.cpp. Please help
//Vectors.h
#include "stdafx.h"
#include "driver.h"
#include "targetver.h"
#include <iomanip>
#include <array>
#include <stdio.h>
#include <tchar.h>
#include <string>
using namespace std;
class Vector
{
double* arr; // pointer to the first element of this myvec
int cap; // number of elements arr can hold (i.e. size of underlying array)
int n; // size of this myvec
int sz = 1;
// Increases the capacity of the underlying array to be sz. If sz
// is smaller than the current capacity then nothing is done.
// create an empty vector
void increase_capacity(int sz)
{
if (sz <= cap) return;
double* new_arr = new double[sz]; // allocate a new array
for (int i = 0; i < cap; ++i)
{ // copy old vector into new one
new_arr[i] = arr[i];
}
cap = sz; // set the new capacity
delete[] arr; // delete the old vector
arr = new_arr;
}
public:
Vector()
{
arr = new double[sz];
}
Vector(int n)
{
arr = new double[n];
}
int size() const
{
return n;
}
void push_back(double x)
{
if (n >= cap) increase_capacity(2 * cap);
arr[n] = x;
++n;
}
double capacity(int i, double val)
{
if (i < 0 || i >= n) cout << ("range error");
arr[i] = val;
return val;
}
double at(int n) const
{
if (n < 0 || n >= n) cout << ("range error");
return arr[n];
}
void clear()
{
delete[] arr;
Vector();
}
~Vector()
{ // destructor
delete[] arr;
}
};
//driver.cpp
const int TEST_VALUE1 = 21;
const int TEST_VALUE2 = 31;
const int TEST_VALUE3 = 41;
const int MAX = 12;
int main( )
{
// Create a default vector
Vector sam;
// push some data into sam
cout << "\nPushing three values into sam";
sam.push_back(TEST_VALUE1);
sam.push_back(TEST_VALUE2);
sam.push_back(TEST_VALUE3);
cout << "\nThe values in sam are: ";
// test for out of bounds condition here
// and test exception
for (int i = 0; i < sam.size( ) + 1; i++)
{
try
{
cout << sam.at(i) << " ";
}
catch(int badIndex)
{
cout << "\nOut of bounds at index " << badIndex << endl;
}
}
cout << "\n--------------\n";
// clear sam and display its size and capacity
sam.clear( );
cout << "\nsam has been cleared.";
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capacity is now " << sam.capacity() << endl;
cout << "---------------\n";
// Push 12 values into the vector - it should grow
cout << "\nPush 12 values into sam.";
for (int i = 0; i < MAX; i++)
sam.push_back(i);
cout << "\nSam's size is now " << sam.size( );
cout << "\nSam's capcacity is now " << sam.capacity( ) << endl;
cout << "---------------\n";
cout << "\nTest to see if contents are correct...";
// display the values in the vector
for (int i = 0; i < sam.size( ); i++)
{
cout << sam.at(i) << " ";
}
cout << "\n--------------\n";
cout << "\n\nTest Complete...";
cout << endl;
system("PAUSE");
return 0;
}
Here are the requirements for my class, of which are relevant:
A default constructor that creates a vector that is empty. Its size will be zero and its capacity will be two. Remember that size refers to the number of elements currently stored in the vector.
A parameterized constructor that creates a vector of capacity n. Its size will initially be zero.
A function size( ) that returns the size of your vector. The size is defined as the number of integer values that have been stored in the vector. The size will change as integer values are added.
A function capacity( ) that returns the capacity of the vector. The capacity is defined as the number of integer values that can be stored in the vector. The capacity changes when the vector grows.
Your defined capacity method takes two arguments, the way you've made it. It probably shouldn't, because as you are trying to use it, it should be purely dependent on the object and just return the value you want. You have the choice between providing arguments: Vector::capacity(i, var), or changing your definition to accept 0 arguments.
From what I understand about the actual Vector class method capacity() in C++, you shouldn't be taking any arguments. However, from what I understand about your definition of capacity, you're modifying a component, which you do need to supply both a float and an int, which you are not doing when you write Vector::Capacity().
The first part of your code seems strange (preceding public:), since it is not a constructor but you seem to be initializing a vector. Also, your variable sz should be renamed to cap, since it is the capacity, not the size, and your variable n to sz since it is the size.. (I understand why you are confused...)
To keep things easy for myself I changed the double* to a double. Feel free to change it back. I also wrote sz as size because two letters make it a lot prettier to look at.
class Vector
{
// initialise array myvec in constructors.
int cap; // number of elements arr can hold (i.e. size of underlying array)
int size; // size of this myvec (same as n)
At this point, there is no use to "create an empty vector" outside of a constructor. Therefore I moved the bit here into the two constructors.
public:
Vector()
{
double[2] arr; //creates an array of size two, that is empty.
cap = 2;
size = 0;
}
Vector(int n)
{
double[n] arr; //creates an array of size n, also empty.
cap = n;
size = 0;
}
int size() const
{
return size;
}
void push_back(double x)
{
if (size >= cap) increase_capacity(2 * cap);
arr[size] = x;
++size;
}
double capacity()
{
return cap;
}
The rest of the functions seem ok. Note that I may not have gotten the memory management right, especially with the constructor. If I did, I was bound to get it wrong. I hope you can figure that out.
EDIT: After looking at the pushback method, I now see why you had the increase_capacity method. Here's an edit relative to my code:
void increase_capacity(int new_cap)
{
//if (sz <= cap) return; THIS IS NOT NEEDED, since the function is only called when size > cap.
double[new_cap] arr; // allocate a new array - Note that once again I'm not using pointers, you may want to change this.
for (int i = 0; i < cap; ++i)
{ // copy old vector into new one
new_arr[i] = arr[i];
}
cap = new_cap; // set the new capacity
delete[] arr; // delete the old vector
arr = new_arr;
}

Incorrect Variable output with Vector Class C++

My output for the call to the temporary array size wont correctly output. It resizes as according, but I can't get the MAX to display the new value of the new array. My error is within the Resize function within the class.
#include <iostream>
#include <vector>
#include <string>
#include <math.h>
#include <ctime>
using namespace std;
class VectorClass {
private:
int * Vector;//This will be our resizeable array
int Size; //Keep track of vector current size
int MAX=10;
int growth = 5;
int num;
int Resize(int growth, int MAX);
public:
VectorClass(int growth, int Size);
~VectorClass();
int AddItem(int num);
void RemoveItem();
void Print(void);
};
VectorClass::VectorClass(int growth, int Size)
{
Size = 10;
growth = 5;
Vector = new int[Size];
}
VectorClass::~VectorClass()
{
cout << "Destructor was called." << endl;
}
//Will insert num into the vector at the current open position
int VectorClass::AddItem(int num)
{
Vector[Size] = num;
Size++; //Indicate that there isnt as much free space
if (Size == MAX)
{
Resize(Size, MAX);
}
Print();
return num;
}
//Get rid of the most recently added item
void VectorClass::RemoveItem()
{
Size--; //Tricks the vector into one fewer elements in it it currently does
Print();
}
int VectorClass::Resize(int growth, int MAX)
{
cout << "Array is full! Resizing the Array!" << endl;
//Step 1: make a copy
int * temp = new int[MAX]; //Make a new array, same size as exiting array
//loop that copies the original into the copy
for (int i = 0; i<MAX; i++)
{
temp[i] = Vector[i];
}
//Step 2: Delete the original
delete[] Vector; //Deletes all elements in the array Vector from the Heap
//Step 3: Make a bigger vector
Vector = new int[MAX + growth];
//Step 4: Reverse the copy and record the size change
for (int i = 0; i<MAX; i++)
{
Vector[i] = temp[i];
}
MAX = MAX + growth;
//Step 5: Delete the copy
delete[] temp;
cout << "Resize was called.\n" << endl;
return MAX;
}
void VectorClass::Print()
{
cout << "*******************************************************" << endl;
for (int i = 0; i< Size; i++)
{
cout << Vector[i] << endl;
}
cout << "Size = " << Size << "\tMAX = " << MAX << "\t Growth = " << growth << endl << endl;
cout << "*******************************************************" << endl;
}
int main(void)
{
VectorClass V(5,10);
for (int i = 0; i <= 4; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector #1
V.Print();
//Delete 2 Items
V.RemoveItem();
V.RemoveItem();
//Add 9 random Numbers
for (int i = 0; i <= 8; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector
V.Print();
system("pause");
return 0;
}
Several things are wrong with you code. The first one, probably not the one you care about most, is that you never free the memory. You should do it in your destructor, or even better use a std::unique_ptr to handle your memory.
Now, i believe you are yourself confused about your own variables. I see that you possess a variable member named num that you never use. Even worse, you have a parameter in AddItem with the same name. Are you sure it does what you want? The same is true for growth. I would advise you to name your member variable differently, so that you know what they are quickly. I prefixe them with "m_" for example, but you can do as you wish.
You do not need to declare your function parameters inside your class. Only in the function prototype.
Then, in your AddItem function, you use your variable Size to determine where to add the new element, but you initialize your array with it too, which means that not only you do not add your elements at the beginning of your array, you try to write them in memory you do not own!
I could continue for a long time. I am sorry but it only appears to me that you do not know C++ at all. You should go learn the basics again, and maybe start with an easier project to begin your C++ learning.
Good luck :-)

A heap has been corrupted when trying to run code

When ever I run my program it breaks and has the error "A heap has been corrupted" when debugging the program, it actually will go through the whole thing just fine and break on the system("PAUSE") which seems like an odd place to have an error. I am clueless where the issue is. The program worked just fine, until I added the operator overload for + and OS
Below is my code:
MAIN.CPP
#include "stdafx.h"
#include "vector.h"
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(Vector);
int main()
{
cout << "\nCreating a vector Sam of size 4.";
Vector sam(4);
cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; i++)
sam.push_back(i);
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nCreating a vector Joe of size 4.";
Vector joe(4);
cout << "\nPush 6 values into the vector.";
for (int i = 0; i < 6; i++)
joe.push_back(i * 3);
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
cout << "\nTest the overloaded assignment operator \"joe = sam\": ";
joe = sam;
cout << "\nHere is sam: ";
cout << sam;
cout << "\n---------------\n";
cout << "\nHere is joe: ";
cout << joe;
cout << "\n---------------\n";
// pass a copy of sam by value
printV(sam);
system("PAUSE");
return 0;
}
void printV(Vector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
VECTOR.H
#pragma once
#include <iostream>
#include "stdafx.h"
using namespace std;
class Vector
{
private:
int vectorSize;
int vectorCapacity;
int *vectorArray;
public:
//A default constructor that creates an vector with a default capacity of 2
Vector();
//A parameterized constructor that creates a vector of capacity n
Vector(int n);
// A function, size(), that returns the size of your vector.
int size();
// A function, capacity(), that returns the capacity of the vector.
int capacity();
// A function, clear(), that deletes all of the elements from the vector and resets its size to zero and its capacity to two.
void clear();
// A function push_back(int n) that adds the integer value n to the end of the vector.If the vector is not large enough to hold this additional value, you must make the vector grow.Your grow algorithm should double the current capacity of the vector.Don't forget to consider the case where the initial capacity of the vector is zero.
void push_back(int n);
// A function at(int n) that returns the value of the element at position n in the vector.If the index n is greater than the size() of the vector, this function should throw an exception.
int at(int n);
friend ostream& operator<<(ostream& os, Vector vt);
Vector operator=(Vector&);
VECTOR.CPP
#include "stdafx.h"
#include "vector.h"
Vector::Vector()
{
vectorSize = 0;
vectorCapacity = 0;
vectorArray = 0;
}
// Create new array with given capacity
Vector::Vector(int n)
{
vectorCapacity = n;
vectorArray = new int[vectorCapacity];
}
//Return array size
int Vector::size()
{
return vectorSize;
}
// Return array capacity
int Vector::capacity()
{
return vectorCapacity;
}
// clear array values
void Vector::clear()
{
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = 0;
vectorCapacity = 2;
}
// Add number to array and double array size if needed
void Vector::push_back(int n)
{
int test = 100;
if (vectorCapacity > vectorSize)
{
vectorArray[vectorSize] = n;
vectorSize++;
}
else {
if (vectorCapacity == 0) {
vectorArray = new int[4];
vectorArray[0] = n;
vectorCapacity = 4;
vectorSize++;
}
else {
int newCapacity = vectorCapacity * 2;
// Dynamically allocate a new array of integers what is somewhat larger than the existing array.An algorithm that is often used is to double the size of the array.
int *tempArray = new int[newCapacity];
// Change capacity to be the capacity of the new array.
vectorCapacity = newCapacity;
// Copy all of the numbers from the first array into the second, in sequence.
for (int i = 0; i < Vector::size(); i++)
{
tempArray[i] = vectorArray[i];
}
delete[] vectorArray;
vectorArray = new int[newCapacity];
for (int i = 0; i < Vector::size(); i++)
{
vectorArray[i] = tempArray[i];
}
delete[] tempArray;
// Add the new element at the next open slot in the new array.
vectorArray[vectorSize] = n;
// Increment the size;
vectorSize++;
}
}
}
// Return Value and given point in array
int Vector::at(int n)
{
return vectorArray[n];
}
// Cout Vector
ostream& operator<<(ostream& os, Vector vt)
{
int size = vt.size();
for (int i = 0; i < size; i++) {
os << "index " << i << " is " << vt.at(i) << endl;
}
return os;
}
// Set one vector to equil another
Vector Vector::operator=(Vector& right) {
// Clear array on left
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = right.size();
vectorCapacity = right.size() * 2;
// Assign values from left to right
for (int i = 0; i < vectorSize; i++)
{
vectorArray[i] = right.at(i);
}
return vectorArray[0];
}
The problem is operator=()
Why ?
You start with sam having a capacity of 4. You push back 12 items in it. When you reach the 5th element, the capacity is doubled from 4 to 8. Then you then reach the 9th element, the capacity is increased to 24.
You then have joe with an initial capacity of 4. You push back 6 items in it. When you reach the 5th element, its capacity is increased to 8.
When you then do joe = sam, your operator overwrites joe's size and capacity but without verifying that the capacity matches, and without allocating missing capacity. As you then try to copy 12 elements in a vector having in reality only a capacity of 8, you do some collateral damage in memory and corrupt the heap.
Solution
Do not overwrite blindly the capacity. Keep the capacity if it's sufficient. If not, align the capacity and reallocate.
// Set one vector to equal another
Vector Vector::operator=(Vector& right) {
//...
if (vectorCapacity < right.vectorCapacity) {
delete[] vectorArray; // assuming pointer is either nullptr or valid array
vectorArray = new int[right.vectorCapacity];
vectorCapacity = right.vectorCapacity;
}
vectorSize = right.size();
// Assign values from left to right
//...
return *this;
}
Note that it would be better to return the vector by reference !
There are lots of errors, but the one that causes the described symptoms is the operator= never allocates a new array of int for vectorArray
Each use of sizeof(vectorArray) is also wrong. That is just the size of a pointer, not the allocation of the area pointed to.
Each place that does vectorArray[i] = '\0'; is at best pointless, and whatever was intended, that is the wrong way to do it. Enough so I can't even guess the intent.
In the clear function the only necessary step was vectorSize = 0; The rest was at best pointless. Setting capacity to 2 there is bizarre, though it does no major harm.
operator= ought to have return type Vector& and not Vector and should return *this not construct a Vector whose capacity is a value from the old one. In general, almost any operator= member of a class should return *this. Exceptions to that rule are way beyond the level where you are currently trying to learn.
Given all of the answers so far, the other issue is that you failed to implement a user-defined copy constructor:
Vector(const Vector& n);
This function has to be implemented correctly since you have functions returning Vector by value. Since you didn't implement it, copying will not work correctly.
Second issue is that you should be returning the Vector by reference, not by value in the operator= function.
My first suggestion is to take whatever code you have now in your operator= and do the work of the "real" copying in the copy constructor. Here is a streamlined version of what the copy constructor should look like:
#include <algorithm>
//..
Vector::Vector(const Vector& rhs) : vectorCapacity(rhs.vectorCapacity),
vectorArray(new int[rhs.vectorCapacity]),
vectorSize(rhs.size())
{
std::copy(rhs.vectorArray, rhs.vectorArray + rhs.vectorCapacity, vectorArray);
}
Note the usage of the member initialization list, and the call to the function std::copy (you could also have written a loop, but just to show you that there are functions that do the copy without hand-written loops).
The second thing is that your destructor should simply do this:
Vector::~Vector()
{ delete [] vectorArray; }
Then operator= becomes very simple using copy / swap.
#include <algorithm>
//...
Vector& operator=(const Vector& v)
{
Vector temp = v;
swap(this.vectorCapacity, temp.vectorCapacity);
swap(this.vectorArray, temp.vectorArray);
swap(this.vectorSize, temp.vectorSize);
return *this;
}
This works only if the copy constructor and destructor work correctly, since operator= takes advantage of these functions.
Read more about the Rule of 3 and the copy / swap idiom.

Operator Overloading

I'm new to C++, this is my first week since the upgrade from fortran. Sorry if this is a simple question, but could someone help me with operator overloading. I have written a program which has two classes. One object contains a vector and two scalars, the other class simply contains the first object. In a test implementation of this code I suspect the operator overloading to be at fault. The program tries to accomplish the following goals:
1) Initialize first structure.
2) Initialize a second structure containing the initialized first structure. After this is imported, the value val0 = 10 is added to every element of the vector in the enclosing structure, structure2.structure1 .
3) Output structure1 and structure2 variables to compare.
For this simple program my output is:
100
100
0
0
0 0 10
1 1 11
2 2 12
3 3 13
...
I was expecting:
100
100
0
10
0 0 10
1 1 11
2 2 12
3 3 13
...
Clearly my overloaded = operator is copying my vector properly, but one of the scalars? Could someone help?
#include <iostream>
using namespace std;
typedef double* doublevec;
// This first class contains a vector, a scalar N representing the size of the vector, and another scalar used for intializing the vector.
typedef class Structure1
{
int N, vec0;
doublevec vec;
public:
// Constructor and copy constructor.
Structure1(int Nin, int vecin) : N(Nin), vec0(vecin) { vec = new double [N]; for(int i = 0; i < N; i++) { vec[i] = i + vec0; } }
Structure1(const Structure1& structurein);
// Accessor functions:
int get_vec0() { return vec0; }
int get_N() { return N; }
doublevec get_vec() { return vec; }
// Overide equivalence operator:
Structure1& operator=(const Structure1& right)
{
//Handle Self-Assignment
if (this == &right) return *this;
N = right.N;
vec0 = right.vec0;
for (int i = 0; i < N; i++)
{
vec[i] = right.vec[i];
}
return *this;
}
// Destructor:
~Structure1() { delete []vec; }
} Structure1;
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for(int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
}
// This class just contains the first structure.
typedef class Structure2
{
Structure1 structure;
// Mutator Function:
void mutate_structure();
public:
// Constructor:
Structure2(const Structure1& structurein) : structure(structurein) { mutate_structure(); }
// Accessor Function:
Structure1 get_structure() { return structure; }
// Destructor:
~Structure2() {}
} Structure2;
void Structure2::mutate_structure()
{
int N = structure.get_N();
Structure1 tempstruct(N,10);
structure = tempstruct;
}
int main (int argc, char * const argv[])
{
const int N = 100;
Structure1 structure1(N,0);
Structure2 structure2(structure1);
cout << structure1.get_N() << endl;
cout << structure2.get_structure().get_N() << endl;
cout << structure1.get_vec0() << endl;
cout << structure2.get_structure().get_vec0() << endl;
for(int i = 0; i < N; i++)
{
cout << i << " " << structure1.get_vec()[i] << " " << structure2.get_structure().get_vec()[i] << endl;
}
return 0;
}
it looks like vec0 isn't initialized by your copy constructor...
Try modifying your copy constructor to:
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for (int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
// ADD THIS LINE
vec0 = structurein.vec0;
}
Your copy-constructor Structure1::Structure1(const Structure1 &) doesn't copy vec0. It's not getting initialised at all, so gets whatever is in memory.
Also, you might want to check Structure1's operator=. If you assign a large vector to a small vector, then you'll potentially overflow the array in the destination. You might need to reallocate memory in operator=.