I am in my first C++ this semester and am having some issues with a MyVector class I created earlier on in the class. I made variables global for the object which is a "NO NO" as my teacher said for object oriented programming. I believed I have declared the variables correctly now, but ever since I am receiving an
"Invalid allocation size: 4294967295 bytes." When calling my push_back function.
Below is my code (driver.cpp, MyVector.h, and MyVector.cpp), I understand that using "using namespace std;" is not best practice but this is how my teacher wants it.... I don't know why.
I have stepped through my code and can't identify what I need to do next. I have a feeling it is how I had the variable declared before. They were previously in the MyVector.cpp declared globally as follows before the change.
1 2 3 4 5 6
//Declarations
int vSize;
int* myArray;
int startCap = 2;
constint TWO = 2;
constint ZERO = 0;
Any help or a point in the right direction would be appreciated.
#include <iostream>
#include "MyVector.h"
usingnamespace std;
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);
int main( )
{
cout << "\nCreating a vector Sam of size 4.";
MyVector 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.";
MyVector 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);
cout << endl;
system("PAUSE");
return 0;
}
void printV(MyVector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
#include <fstream>
usingnamespace std;
class MyVector
{
public:
int vSize;
int* myArray;
int startCap;
//Constructor
MyVector ();
MyVector (int n);
//Deconstructor
~MyVector ();
//Copy Constructor
MyVector(const MyVector&);
//Overloaded Assignment Operator
MyVector& operator=(const MyVector&);
//Getter Function: size
//Purpose: Return the size of the vector
//Return Type: int
//Parameters: NONE
int size () const;
//Getter Funcation: capacity
//Purpose: Return the capacity of the vector
//Return Type: int
//Parameters: NONE
int capacity () const;
//Setter Funcation: clear
//Purpose: Clears the contents of the vector and sets the siz to zero and the capacity to two
//Return Type: void
//Parameters: NONE
void clear ();
//Setter Funcation: push_back
//Purpose: Adds integer to vector. If vector is not big enough double the vectors current capacity
//Return Type: void
//Parameters: int n
void push_back (int n);
//Getter Function: at
//Purpose: Return value of emement at position n
//Return Type: Int
//Parameters: int n
int at (int n) const;
// overloaded << operator - a nonmember
// make it a friend so it can see the array
friend ostream& operator<<(ostream& out, const MyVector& s);
};
#include "MyVector.h"
#include <iostream>
#include <array>
usingnamespace std;
//default constructors
MyVector::MyVector()
{
int startCap = 2;
int vSize = 0;
myArray = newint[startCap];
}
MyVector::MyVector(int n)
{
int startCap = n;
int vSize = 0;
myArray = newint[startCap];
}
//Deconstructor
MyVector::~MyVector()
{
//deleting myArray and clearing it
if (myArray != NULL)
{
delete [] myArray;
myArray = NULL;
}
}
// Copy constructor
// Purpose: Copy the data into this Array
// Parameters: a MyVector object
// Returns: none
MyVector::MyVector( const MyVector& v)
{
// Be sure that the string is not null
if ( v.myArray != NULL )
{
// allocate storage and copy char array
startCap = v.startCap;
//theStr = new char[strlen(b.theStr) + 1];
myArray = newint[startCap];
//strncpy(theStr, b.theStr, theStrLen );
for (int i = 0; i < startCap; i++)
myArray[i] = v.myArray[i];
}
else // nothing to copy
{
myArray = NULL;
startCap = 0;
}
}
// The overloaded assignment operator
MyVector& MyVector::operator= (const MyVector& v)
{
// test for self-copy
if (this == &v)
return *this;
// Consider two cases.
if (startCap >= v.startCap) // there is room
{
if (v.myArray != NULL)
{
for (int i = 0; i < startCap; i++)
{
this->myArray[i] = v.myArray[i];
}
}
else // copying a null string
myArray = NULL;
startCap = v.startCap;
return *this;
}
else // not enough room
{
// delete the original array
delete [] myArray;
startCap = v.startCap;
if (startCap > 0) // okay, something to copy
{
// allocate the storage and copy
myArray = newint[startCap + 1];
for (int i = 0; i < vSize; i++)
{
this->myArray[i] = v.myArray[i];
}
}
else // nothing to copy
myArray = NULL;
return *this;
}
}
//Getter Function: size
//Purpose: Return the size of the vector
//Return Type: int
//Parameters: NONE
int MyVector::size() const
{
return vSize;
}
//Getter Funcation: capacity
//Purpose: Return the capacity of the vector
//Return Type: int
//Parameters: NONE
int MyVector::capacity() const
{
return startCap;
}
//Setter Funcation: clear
//Purpose: Clears the contents of the vector and sets the siz to zero and the capacity to two
//Return Type: void
//Parameters: NONE
void MyVector::clear()
{
//clearing the array and setting the array to the default cap of 2 and size of 0
if (myArray != NULL)
{
delete [] myArray;
myArray = NULL;
}
vSize = 0;
startCap = 2;
int* myArray = newint[startCap];
}
//Setter Funcation: push_back
//Purpose: Adds integer to vector. If vector is not big enough double the vectors current capacity
//Return Type: void
//Parameters: int n
void MyVector::push_back(int n)
{
//verifying the we are not writting the value
//past the capacity of the array
if(vSize + 1 > startCap)
{
//Doubling the array size
startCap = vSize * 2;
//creating a temp array
int* temp = newint[startCap];
//for loop copying the contents of myArray to temp
for (int i = 0; i < vSize; i++)
{
temp[i] = myArray [i];
}
//deleting the myArray
delete[] myArray;
//copying myArray from temp
myArray = temp;
}
//finding the end of the array and incrementing and adding one to the array
myArray[vSize] = n;
vSize++;
}
//Getter Function: at
//Purpose: Return value of emement at position n
//Return Type: Int
//Parameters: int n
int MyVector::at(int n) const
{
//If statment that returns value of the point in the array
//or throws an error telling the user the index at which it failed
if(n < vSize)
return myArray[n];
throw n;
}
ostream& operator<<(ostream& out, const MyVector& s)
{
for (int i = 0; i < s.vSize; i++)
out << s.myArray[i] << ' ';
return out;
}
#include <iostream>
#include "MyVector.h"
usingnamespace std;
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);
int main( )
{
cout << "\nCreating a vector Sam of size 4.";
MyVector 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.";
MyVector 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);
cout << endl;
system("PAUSE");
return 0;
}
void printV(MyVector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
Another question, do you see anything wrong with my the following code?
Why is startCap a member of the class? How does it differ from vSize? Why isn't vSize updated for the target object in operator= or accessed for the source object in operator=? Why would you ever set myArray to NULL without freeing the memory first?
Great questions, which inevitably led me to my answer...
The startCap and vSize are used for the number of actual object in the array and for the capacity of the array. Updated the vSize for the target object updated the number of object in the array which allowed the whole array to be copied over.
The final question's answer is simply I don't know. Looking at example code I threw this together. I have now removed the NULL seeing that this was incorrect.
It looks as though the MyVector& MyVector::operator= (const MyVector& v) is working as it should.
I am now sure why but when I call the printV(sam); it will rattle off the array that was copied but continue until the program crashes. Like so...
-----------------
Printing a copy of a vector
0 1 2 3 4 5 6 7 8 9 10 11 -842150451 -842150451 -842150451 -842150451 -33686019 -1414812757 ......
Is this because of the following code?
1 2 3 4 5 6
ostream& operator<<(ostream& out, const MyVector& s)
{
for (int i = 0; i < s.vSize; i++)
out << s.myArray[i] << ' ';
return out;
}
Not having seen your updated code, I can only assume that you are still failing to update vSize at some point. Note that in the code you posted above it is not set properly in the copy constructor or operator=.
Having taken a closer look at the class code, I see why startCap is a member of the class. What I don't see is why it is named startCap instead of capacity, since it does not remain the starting capacity but reflects the actual capacity of the array. My question was motivated by the inaccurate name.