Trying to Overload the << Operator, getting errors - c++

I am working on overloading the << operator for my MyVector class. It all looks correct to me but I am getting errors when I try to run it. What am I doing wrong?
The first error is (I think) "unexpected token(s) preceding ';' " for line 84 in my .h file. (I say "I think" because I accidentally sorted the errors by description and don't know how to get it back to the default sort. If you can also advise me on how to do that, I would appreciate it.)
Thank you for your time!
MyVector.h
#pragma once
#include <iostream>
class MyVector
{
private:
//declaring variables
int *myPointer;
int vectorSize;
int vectorCapacity;
const int BASE_CAPACITY = 2;
public:
//Default Constructor
//Purpose: Create vector with default capacity of 2
//Parameter: void
//Return: None
MyVector();
//Parameterized Constructor
//Purpose: Creates a vector of capacity "n"
//Parameter: int
//Return: None
MyVector(const int);
//Default Deconstructor
//Purpose: Deletes any dynamically allocated storage
//Parameter: void
//Return: None
~MyVector();
//Copy Constructor
//Purpose: Copy the data of the vector
//Parameter: a MyVector object
//Return: None
MyVector(const MyVector&);
//Overloaded Assignment Operator
//Purpose: Copy one vector to the other when = is used
//Parameter: a MyVector object
//Return: a MyVector object
MyVector& operator=(const MyVector&);
//The size Function
//Purpose: returns the size of the vector
//Parameter: void
//Return: int
int size() const;
//The capacity Function
//Purpose: returns the capacity of the vector
//Parameter: void
//Return: int
int capacity() const;
//The clear Function
//Purpose: Deletes all elements from the vector and resets the size and capacity
//Parameter: void
//Return: None
void clear();
//The push_back Function
//Purpose: adds an integer to the vector
//Parameter: int
//Return: None
void push_back(const int);
//The at Function
//Purpose: returns the value of the element at position n
//Parameter: int
//Return: int
int at(const int) const;
// Overloaded << operation
// Purpose: Output a Vector
// Parameter: an ostream and a vector
// Return: ostream
friend ostream& operator<<(ostream& out, const MyVector& rho);
};
MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
MyVector::MyVector()
{
//create a vector with size 0 and capacity 2
vectorSize = 0;
vectorCapacity = BASE_CAPACITY;
myPointer = new int[vectorSize];
}
MyVector::MyVector(int n)
{
//create a vector of capacity n with the size 0
vectorSize = 0;
vectorCapacity = n;
myPointer = new int[vectorSize];
}
MyVector::~MyVector()
{
//check to see if 'myPointer' has a value and delete it
if (myPointer != NULL)
{
delete[] myPointer;
myPointer = NULL;
}
}
MyVector::MyVector(const MyVector& b)
{
if (b.myPointer != NULL)
{
vectorCapacity = b.vectorCapacity;
vectorSize = b.vectorSize;
myPointer = new int[vectorCapacity];
for (int i = 0; i < vectorSize; i++)
{
myPointer[i] = b.at(i);
}
}
else
{
delete[] myPointer;
}
}
MyVector& MyVector::operator=(const MyVector& rho)
{
//test for self assignment
if (this == &rho)
return *this;
// clean up the vector on the left side
delete[] this->myPointer;
// create a new vector of the correct size and capacity
vectorSize = rho.vectorSize;
vectorCapacity = rho.vectorCapacity;
this->myPointer = new int[vectorSize];
// copy the data over
for (int i = 0; i < vectorSize; i++)
{
this->myPointer[i] = rho.myPointer[i];
}
//return this object
return *this;
}
int MyVector::size() const
{
//return the size of the vector
return vectorSize;
}
int MyVector::capacity() const
{
//return the capacity of the vector
return vectorCapacity;
}
void MyVector::clear()
{
//clear the vector and reset it to a size of 0 and capacity of 2
vectorSize = 0;
vectorCapacity = BASE_CAPACITY;
delete[] myPointer;
myPointer = new int[vectorSize];
}
void MyVector::push_back(int addToVector)
{
//this variable will be used to double the capacity
const int DOUBLE_CAPACITY = 2;
//check to see if the size of the vector has reached the capacity
if (!(vectorSize < vectorCapacity))
{
//make sure the capacity of the vector is greater than 0
if (vectorCapacity > 0)
{
vectorCapacity *= DOUBLE_CAPACITY;
}
else
{
//if vector capacity is 0 or less then the capacity equals 2
vectorCapacity = BASE_CAPACITY;
}
//create a tempVector that will have double the capacity of the last vector.
int *tempVector = new int[vectorCapacity];
//copy the contents of the old vector to the tempVector
if (myPointer != NULL)
{
for (int i = 0; i < vectorCapacity; i++)
{
tempVector[i] = myPointer[i];
}
}
// delete the old array using the destructor
MyVector::~MyVector();
//set the pointer to the new tempVector
myPointer = tempVector;
}
//add the passed in value to the vector
myPointer[vectorSize] = addToVector;
//increment the size of the vector
vectorSize++;
}
int MyVector::at(int x) const
{
//throw exception if index outside the range of the vector
if (x > (vectorSize - 1))
{
throw x;
}
//return the value of the integer stored at index x
return myPointer[x];
}
ostream& operator<<(ostream& out, const MyVector& rho)
{
// output each value in the vector
for (int i = 0; i < rho.size; i++)
{
out << rho.at(i) << " ";
}
// return the ostream
return out;
}

friend ostream& operator<<(ostream& out, const MyVector& rho);
I'm assuming this is the line in question. You need to put std:: in front of ostream so it knows where to look for it. Although you put using namespace std; in the implementation file, that doesn't affect the header.
friend std::ostream& operator<<(std::ostream& out, const MyVector& rho);
On another note, don't use using namespace std;.

Related

Array Index Overload Bug

Why does this code result in the second element of the array being printed as 0, irrespective of the value that was specified in the definition of the integer array object?
The output of the code below is 7 0 3 4 5 6 instead of 7 2 3 4 5 6, what would be the reason for this behavior?
// Overloading operators for Array class
#include<iostream>
#include<cstdlib>
using namespace std;
// A class to represent an integer array
class Array
{
private:
int *ptr;
int size;
public:
Array(int *, int);
// Overloading [] operator to access elements in array style
int &operator[] (int);
// Utility function to print contents
void print() const;
};
// Implementation of [] operator. This function must return a
// reference as array element can be put on left side
int &Array::operator[](int index)
{
if (index >= size)
{
cout << "Array index out of bound, exiting";
exit(0);
}
return ptr[index];
}
// constructor for array class
Array::Array(int *p = NULL, int s = 0)
{
size = s;
ptr = NULL;
if (s != 0)
{
ptr = new int[s];
for (int i = 0; i < s; i++)
ptr[i] = p[i];
delete ptr;
}
}
void Array::print() const
{
for(int i = 0; i < size; i++)
cout<<ptr[i]<<" ";
cout<<endl;
}
// Driver program to test above methods
int main()
{
int a[] = {1, 2, 3, 4, 5, 6};
Array arr1(a, 6);
arr1[0] = 7;
arr1.print();
arr1[8] = 6;
return 0;
}
In the Array constructor, immediately after allocating and filling the dynamically allocated buffer at ptr, the buffer is released with
delete ptr;
All accesses of the buffer at ptr after this point invoke undefined behaviour. Side note: This should have been delete[] ptr; to ensure that the array was released correctly.
The solution: Don't do that!
Add a destructor to free ptr when Array goes out of scope and is done with the buffer.
// destructor for array class
Array::~Array()
{
delete[] ptr;
}
The compiler will automatically generate a destructor for you, but that generic destructor is not qualified to know whether or not it is safe to delete[] what's at a pointer member. It might not be an array, the allocation could be owned by another object (See What is ownership of resources or pointers?) or perhaps not allocated dynamically with new.
This brings up a side note: The default special member functions that handle copying this object will mindlessly copy the pointer, not the allocation, and leave you with two objects pointing to the same allocation. Sooner or later this will be fatal because one copy will go out of scope before the other and if nothing else tries to access the freed allocation and break the program, the second delete[] will break the program. This issue and its solution is covered in detail at What is The Rule of Three?
The general rule of thumb is to not make a class like this and instead use std::vector. std::vector does all of this and a whole lot more.
I modified the code as such to include an explicit default constructor and copy constructor, also included the std::out_of_range exception but am not sure if the latter is properly implemented.
This was done as an exercise in handling arrays without utilizing the vector container from STL.
Added a swap member function and assignment operator but getting a few error msgs.
class "Array" has no member "swap"
member "Array::size" (declared at line 12) is inaccessible
'operator=' must be a member function
'this' may only be used inside a nonstatic member function
// Overloading operators for Array class
#include<iostream>
#include<cstdlib>
//#include<vector>
using namespace std;
// A class to represent an integer array
class Array{
private:
int *ptr;
int size;
public:
Array(int *, int);
Array(const Array&);
~Array();
Array& operator= (Array);
// Overloading [] operator to access elements in array style
int &operator[] (int);
// Utility function to print contents
void print() const;
friend void swap(Array& first, Array& second);};
// Implementation of [] operator. This function must return a
// reference as array element can be put on left side
int &Array::operator[](int index){
// try {
// return ptr[index];}
// catch(const out_of_range& oor){
// cerr << "Out of Range error: " << oor.what() << '\n';}
if (index >= size || index < 0){
throw out_of_range("Index out of Range error");
}
return ptr[index];
}
// constructor for array class
Array::Array(int *p = NULL, int s = 0){
size = s;
ptr = NULL;
if (s != 0){
ptr = new int[s];
for (int i = 0; i < s; i++)
ptr[i] = p[i];}
}
// destructor for array class
Array::~Array(){
delete[] ptr;
ptr = NULL;}
// copy constructor for array class
Array::Array(const Array& A) {
size = A.size;
ptr = new int[size];
for (int i = 0; i < size; i++)
ptr[i] = A.ptr[i];}
void Array::swap(Array& first, Array& second){
using std::swap;
swap(first.size, second.size);
swap(first.ptr, second.ptr);}
//Assignment operator for array class
Array::Array& operator=(Array other){
swap(*this, other);
return *this;}
//print function for array elements
void Array::print() const{
cout << "{";
for(int i = 0; i < size; i++)
cout<<ptr[i]<<" ";
cout<<"}"<<endl;}
// Driver program to test above methods
int main()
{
int a[] = {1, 2, 3, 4, 5, 6};
Array arr1(a, 6);
arr1[0] = 7;
arr1.print();
Array arr2 = arr1;
arr2.print();
arr1[-1] = 4;
return 0;
}
Modified print function to exclude space after last array element.
Modified constructor method declaration to include initialized arguments.
Added additional const version of index[ ] operator overload but don't think it's properly implemented or if it would actually be utilized.
#include<iostream>
#include<cstdlib>
// A class to represent an integer array
class Array{
private:
int *ptr;
std::size_t size;
public:
Array(int *p = nullptr, std::size_t s = 0);
Array(const Array&);
~Array();
Array& operator= (Array);
// Overloading [] operator to access elements in array style
int &operator[] (std::size_t);
int const& operator[](std::size_t) const;
// Utility function to print contents
void print() const;
friend void swap(Array& first, Array& second);};
// Implementation of [] operator. This function must return a
// reference as array element can be put on left side
int &Array::operator[](std::size_t index){
puts("overload");
if (index >= size || index < 0){
throw std::out_of_range("Index out of Range error");
}
return ptr[index];
}
int const& Array::operator[](std::size_t index) const{
puts("const overload");
if (index >= size || index < 0){
throw std::out_of_range("Index out of Range error");
}
return ptr[index];
}
// constructor for array class
Array::Array(int *p, std::size_t s){
size = s;
ptr = nullptr;
if (s != 0){
ptr = new int[s];
for (int i = 0; i < s; i++){
ptr[i] = p[i];}
}
}
// destructor for array class
Array::~Array(){
delete[] ptr;
ptr = nullptr;}
// copy constructor for array class
Array::Array(const Array& A) {
size = A.size;
ptr = new int[size];
for (int i = 0; i < size; i++){
ptr[i] = A.ptr[i];}
}
//swap friend function of assignment operator
void swap(Array& first, Array& second){
using std::swap;
swap(first.size, second.size);
swap(first.ptr, second.ptr);}
//Assignment operator for array class
Array& Array::operator=(Array other){
swap(*this, other);
return *this;}
//print function for array elements
void Array::print() const{
std::cout << "{";
for(int i = 0; i < size; i++){
std::cout << ptr[i];
if (i == size-1){
continue;}
std::cout<<" ";
}
std::cout<<"}"<< std::endl;}
// Driver program to test above methods
int main()
{
int a[] = {1, 2, 3, 4, 5, 6};
Array arr1(a, 6);
std::cout << arr1[3] << '\n';
arr1[4] = 7;
arr1.print();
Array arr2 = arr1;
arr2.print();
arr1[-1] = 4;
return 0;
}

C++ Int doesn't seem to be initializing and Exception thrown: read access violation

I'm very new to C++ so please excuse the sloppy code.
Here is the code in question:
Bag Class
class Bag {
protected:
Item* _myItems;
int _numItems;
int _size;
public:
Bag();
Bag(int size);
~Bag();
Bag(Bag& original);
void add(Item a);
void remove(int itemnum);
int size();
int numItems();
void operator=(Bag& bag);
Item& operator[] (int i);
};
//Empty constructor
Bag::Bag() {
_numItems = 0;
}
//overloaded constructor
Bag::Bag(int size) {
_numItems = 0;
_myItems = new Item[size];
}
//copy constructor
Bag::Bag(Bag& original) {
//Copies the numItems
_numItems = original._numItems;
//Makes a new copy of the original array
_myItems = new Item[_numItems];
//Copies each element of the original into the new
for (int i = 0; i < _numItems; ++i) {
_myItems[i] = original[i];
}
}
//Destructor
Bag::~Bag(){
delete[] _myItems;
}
//Returns the size of the bag
int Bag::size()
{
return _size;
}
//Returns the number of items in the bag
int Bag::numItems() {
return _numItems;
}
//Add a new item to the bag
void Bag::add(Item a) {
int s = _numItems;
//Create a Item pointer and assign it to the array of the bag
Item* temp = _myItems;
//Assign _myItems to a new, larger array
_myItems = new Item[_numItems++];
//Copy the old array into the new one and nullify all the old array's items
for (int i = 0; i < _numItems - 1; i++) {
_myItems[i] = temp[i];
}
//Destroy the old array
delete[] temp;
//Add the item to the last position
_myItems[_numItems] = a;
}
I am reading a text file line by line. The reading seems to be happening just fine. When I read in I execute this part of the code:
//The main program
int main() {
Pens * onePen = new Pens(1, 2);
Pens * twoPen = new Pens(2, 3);
Bag* bag = new Bag(5);
(*bag).add(onePen);
(*bag).add(twoPen);
bag[0];
bag[1];
int d = 0;
return 0;
}
I keep getting the Read Access Violation (This was 0xc) when I get into the add method. I also notice that when I put in breakpoints to examine the code, _numItems is not 0 but 211. Am I corrupting my memory somehow?
Here is a sample text file that we are using
Simplified version of the Bag and Pen classes (courtesy of PaulMcKenzie):
class Item {
protected:
int code_;
//Sets the method definition for the get/set methods and constructors
public:
Item(int code = -1);
virtual ~Item() {}
int getcode() const;
void setcode(int code);
std::ostream& operator<< (std::ostream& s);
bool operator== (const Item& a) const;
};
Item::Item(int code) : code_(code) {}
int Item::getcode() const { return code_; }
void Item::setcode(int code) { code_ = code; }
std::ostream & Item::operator<<(std::ostream& s)
{
s << " Code - " << code_ << "\n";
return s;
}
bool Item::operator==(const Item & a) const
{
return (code_ == a.getcode());
}
class Pens : public Item
{
private: int packetsize_;
public:
Pens();
Pens(int code, int packetsize);
int getpacketsize() const;
void setpacketsize(int packetsize);
bool operator== (const Pens& a) const;
};
Pens::Pens() :Item() { }
Pens::Pens(int code, int packetsize) : Item(code), packetsize_(packetsize) {}
int Pens::getpacketsize() const { return packetsize_; }
void Pens::setpacketsize(int packetsize) { packetsize_ = packetsize; }
std::ostream& operator<<(std::ostream& s, const Pens& pen)
{
s << " Packet size: " << pen.getpacketsize() << "\n";
return s;
}
bool Pens::operator==(const Pens & a) const
{
return code_ == a.getcode() && packetsize_ == a.getpacketsize();
}
I did not look in depth but this segment caught my eye:
//Add a new item to the bag
void Bag::add(Item a) {
int s = _numItems;
//Create a Item pointer and assign it to the array of the bag
Item* temp = _myItems;
//Assign _myItems to a new, larger array
_myItems = new Item[_numItems++];
//Copy the old array into the new one and nullify all the old array's items
for (int i = 0; i < _numItems - 1; i++) {
_myItems[i] = temp[i];
}
//Destroy the old array
delete[] temp;
//Add the item to the last position
_myItems[_numItems] = a;
}
Please look at this line:
_myItems = new Item[_numItems++];
You create new array with size of _numItems and then increase the _numItems by 1.
Which in my humble opinion leaves you with array of size _numItems-1.
And then you try to use element _myItems[_numItems] so this may be the reason of memory corruption.

project.exe has triggered a breakpoint after system("pause")

I've created my own vector, and when I try to close the console in my driver, I hit enter and get the breakpoint.
#include "MyVector.h"
#include <vector>
// Default constructor
MyVector::MyVector()
{
theData = nullptr;
vecSize = 0;
vecCap = 0;
}
// Parameterized constructor
MyVector::MyVector(int vecCap)
{
// Set vecSize to 0 and vecCap to user input (driver) plus 1 to account
// for null terminator
vecSize = 0;
this->vecCap = vecCap;
theData = new int[vecCap];
}
// Destructor
MyVector::~MyVector()
{
// Run the clear() function
clear();
}
// Copies the vector
void MyVector::copy(const MyVector& toCopy)
{
// Set size and capacity to toCopy's
this->vecCap = toCopy.vecCap;
this->vecSize = toCopy.vecSize;
// Create a temporary pointer array of ints
int* tempArray = new int[];
// Copy data from toCopy to new array
for (int i = 0; i < toCopy.size(); i++)
{
tempArray[i] = toCopy.theData[i];
}
// Point theData to the tempArray
theData = tempArray;
}
// Clears theData and resets vecCap and vecSize to 0
void MyVector::clear()
{
// Check if theData is null
if (theData != nullptr)
{
// Delete theData from heap and set to nullptr
delete[] theData;
theData = nullptr;
// Set vecSize and vecCap to 0
vecSize = 0;
vecCap = 0;
}
}
// Returns size of the vector
int MyVector::size() const
{
return vecSize;
}
// Returns capacity of the vector
int MyVector::capacity() const
{
return vecCap;
}
// Push input values into vector
void MyVector::push_back(int n)
{
// Check if vecSize is too big for vecCap
if (vecSize >= vecCap)
{
// Double vecCap through grow() function
grow(vecCap);
}
// Set theData at element vecSize to user input n, increment vecSize
theData[vecSize] = n;
vecSize++;
}
// Returns index value of vector
int MyVector::at(int vecIdx) const
{
// Check if vecIdx is within bounds
if (vecIdx >= 0 && vecIdx <= vecSize)
{
// Return vector index
return theData[vecIdx];
}
else
{
// Display out of bounds index
throw vecIdx;
}
}
// Doubles the size of the vector capacity
void MyVector::grow(int curCap)
{
// Check if curCap is 0 ro less
if (curCap <= 0)
{
// Set vecCap to CAP_GROWTH -1
vecCap = CAP_GROWTH - 1;
}
else
{
// Increase curCap by CAP_GROWTH (doubled)
vecCap = CAP_GROWTH * curCap;
}
// Create new array
int* newArray = new int[vecCap];
// Copy data to new array
for (int idx = 0; idx < vecSize; idx++)
{
newArray[idx] = theData[idx];
}
// Delete theData
delete[] theData;
// Point theData to new array
theData = newArray;
}
//
MyVector& MyVector::operator=(const MyVector& rho)
{
// Check if the implicit object's address is the same as rho
if (this != &rho)
{
// Clear the implicit object
this->clear();
// Copy the
this->copy(rho);
}
return *this;
}
//
ostream& operator<<(ostream& out, const MyVector& rho)
{
for (int idx = 0; idx < rho.size(); idx++)
{
// Output index of rho, separated by a space
out << rho.at(idx) << " ";
}
return out;
}
I've checked for somewhere I may have tried to re-delete a pointer, but I can't find anything, any it doesn't say why the exception was thrown. Any tips?
Your class does not follow the rule of 3:
What is The Rule of Three?
You are lacking a copy constructor. Your copy function is not a copy constructor. You should implement a proper copy constructor first.
In addition, your copy function has a memory leak, since you never deleted the old data.
Here is an example of a copy constructor
#include <algorithm>
//...
MyVector::MyVector(const MyVector& toCopy) : vecCap(toCopy.vecCap),
vecSize(toCopy.vecSize),
theData(new int[toCopy.capacity()])
{
std::copy(toCopy.theData, toCopy.theData + toCopy.size(), theData);
}
Now, if you really want to keep the copy function (you really don't need it, but for argument's sake you want to keep it), you can use the above copy constructor:
// Copies the vector
void MyVector::copy(const MyVector& toCopy)
{
MyVector temp(toCopy); // calls the copy constructor
std::swap(temp.vecCap, vecCap);
std::swap(temp.vecSize, vecSize);
std::swap(temp.theData, theData);
}
Note that all we did was create a temporary copy, and swap out the temporary copy's data with the current data. The temporary dies off when the function return, taking along with the old data.
Last, your assignment operator can be written using your copy function.
MyVector& MyVector::operator=(const MyVector& rho)
{
copy(rho);
return *this;
}
So in a sense, your copy function served a purpose, if the only purpose was to move some of the code around.
Actually, this is what you should have coded for your assignment operator, even without the changes I suggested. All the assignment operator should have been doing was call copy and return the current object.
In copy function, clear old data, create new data based on capacity:
void MyVector::copy(const MyVector& x)
{
clear();
vecCap = x.vecCap;
vecSize = x.vecSize;
theData = new int[vecCap];
for (int i = 0; i < x.size(); i++)
theData[i] = x.theData[i];
}
Also you are using the same names in argument, it's not wrong the way you are doing it, but it's easier to use a different name:
MyVector::MyVector(int c)
{
vecSize = 0;
vecCap = c;
theData = new int[vecCap];
}

Invalid Allocation Size - Object Variables

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 (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.
//Declarations
int vSize;
int* myArray;
int startCap = 2;
const int TWO = 2;
const int ZERO = 0;
Any help or a point in the right direction would be appreciated.
Thanks in advance!
The Call from the driver.cpp
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);
MyVector.h
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);
};
MyVector.cpp
//default constructors
MyVector::MyVector()
{
int startCap = 2;
int vSize = 0;
myArray = new int[startCap];
}
MyVector::MyVector(int n)
{
int startCap = n;
int vSize = 0;
myArray = new int[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 = new int[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 = new int[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 = new int[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 = new int[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;
}
you are creating a same variable within the constructor and clear, which has the same name is the one in the class, initialize it.
and by the time you leave the constructor or clear, the main variables, don't get any changes.
its an initializing issue, especially the ones in the constructor
in clear function
int* myArray = new int[startCap];
should be
myArray = new int[startCap];
also inside the constructor
int startCap = n;
int vSize = 0;
should be
startCap = n;
vSize = 0;
When you want to assign to an instance variable, don't put the type on the name. That'll create a local variable with the same name as the instance variable instead of assigning to the actual instance variable, causing your instance variables to have incorrect, possibly even uninitialized values. This problem shows up in your first two constructors and your clear method.

Heap error during cout C++

I'm getting an error when trying to cout the return value of Data[index]. If anyone could help me that would be awesome. I know usually these errors are caused by allocated conflicting memory or having a pointer reference a deleted index, etc. Although I don't delete anything so I don't know where this error is coming from.
Header file:
#pragma once
#define INITIAL_CAPACITY 100
#define CAPACITY_BOOST 40
//Encapsulates the C-array
template <typename DATA_TYPE>
class Vector
{
public:
//Default / init-constructor hybrid
Vector(int initialCapacity = INITIAL_CAPACITY)
{
Size=0;
Capacity = initialCapacity;
//Allocate the encapsulated C-array
Data= new DATA_TYPE[Size];
}
//MUST HAVE A COPY-CONSTRUCTOR THAT PERFORMS deep-copy
Vector(const Vector& copyFrom)
{
//Necessary to prevent assignment operator from crashing
//because it will attempt to Delete[] Data whe the Data pointer is garbage.
Data=NULL;
//Use assignment operator to perform the deep copy
*this = copyFrom;
}
//The class MUST have a destructor
~Vector()
{
//Deallocate memory that our class has allocated
delete[] Data;
}
//MUST have an assignment operator that performs deep copy
Vector& operator =(const Vector& copyFrom)
{
//0. Delete the old memory
delete[] Data;
//1. Copy size and Capacity
Size = copyFrom.Size;
Capacity = copyFrom.Capacity;
//2. Allocate Memory
Data = new DATA_TYPE[Capacity];
//3. Copy elemenets
for(int i=0; i < Size; i++)
Data[i]= copyFrom.Data[i];
//All assignment operators should return *this
return *this;
}
//Get accessors to return the values of Size and Capacity
int GetSize() const
{
return this->Size;
}
int GetCapacity() const
{
return Capacity;
}
void Insert(int insertAt, const DATA_TYPE& newElement)
{
//**ASSIGNMENT**
//1. Determine if we have enough capacity for extra element(reallocate)
Size=GetSize();
if(Size>=Capacity)
{
Capacity += CAPACITY_BOOST;
}
//Use a function to check bounds.
if((insertAt > Capacity)||(insertAt < 0))
{
throw "Index is out of bounds";
}
//2.Move the tail
for (int i=Size+1; i > insertAt; i--)
Data[i]=Data[i-1];
//3.Insert element
Data[insertAt]= newElement;
}
//Inserts a new element at the end fo the Vector and increments the size
void Add(const DATA_TYPE& newElement)
{
Insert(Size, newElement);
Size++;
}
void Remove(int index)
{
delete Data[index];
for(i=index; i < Size-1; i++)
Data[i]=Data[i+1];
Size--;
Capacity=Size;
//**ASSIGNMENT**
//Resize. Shrink vector when you have too much capacity
//TEST EVERYTHING
}
// Index operator
DATA_TYPE operator[] (int index) const
{
// Check the bounds and throw an exception
if ( (index < 0) || (index >= Size) )
throw "Error";
return Data[index];
}
private:
//The count of actually used C-array elements
int Size;
//The count of the allocated C-array elements
int Capacity;
//The encapsulated C-array (pointer)
DATA_TYPE* Data;
};
Main:
#include <iostream>
#include "vector.h"
using namespace std;
#define TEST_CAPACITY 100
#define TEST_SIZE 10
template<typename DATA_TYPE>
void PassByValueTest(Vector<DATA_TYPE>passedByValue)
{
}
void main()
{
//myVector is initialized using the default constructor
Vector<int> myVector;
//Populate myVector with some test values
for (int i=0; i< TEST_SIZE; i++)
myVector.Add(i);
//myOtherVector initialized using the init-constructor, initial capacity is 10
//Vector<int> myOtherVector(TEST_CAPACITY);
//Test by passing vector by value
/*
PassByValueTest(myVector);
myVector = myOtherVector;
*/
for(int i = 0; i < TEST_SIZE; i++)
{
cout << myVector[i];
}
system("pause");
}
I guess you should switch:
Data= new DATA_TYPE[Size];
to
Data= new DATA_TYPE[Capacity];
you are doing Data = new DATA_TYPE[0];
Vector(int initialCapacity = INITIAL_CAPACITY)
{
Size=0; // <<<---
Capacity = initialCapacity;
//Allocate the encapsulated C-array
Data= new DATA_TYPE[Size]; // note Size is 0
}
Then access to Data[i] is undefined behavior:
for(int i = 0; i < TEST_SIZE; i++)
{
cout << myVector[i];
}
Side note, you should return int from main, there is no void main in standard:
int main()
{
}