I am not sure what I am doing wrong here but I used Google and found almost the identical code to mine but they did not claim an error. Our assignment is to overload the insertion operator. The problem is that I get an error in the driver for every time I pass SAM or JOE. The error states: Error 2 error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'MyVector' (or there is no acceptable conversion).
Any help is appreciated. Please note that I have not completed this assignment and if another function doesn't seem right, it may be because I haven't work on it.
Thanks in advance.
Driver.cpp
#include <iostream>
#include "MyVector.h"
using namespace 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;
}
My Vector.h
#pragma once
class MyVector
{
private:
int vSize;
int vCapacity;
int* vArray;
void grow();
public:
MyVector();
MyVector(int n);
MyVector(const MyVector& b);
int size() const;
int capacity() const;
void clear();
void push_back(int n);
int& at(int n) const;
MyVector& operator=(const MyVector& rho);
~MyVector();
};
MyVector.cpp
#include "MyVector.h"
#include <iostream>
using namespace std;
MyVector::MyVector()
{
vArray = nullptr;
vSize = 0;
vCapacity = 0;
}
MyVector::MyVector(int n)
{
vArray = new int[vCapacity];
vSize = 0;
vCapacity = n;
}
MyVector::MyVector(const MyVector& b)
{
vSize = b.size();
vArray = new int[vSize];
for (int i = 0; i < b.size(); i++)
{
this->vArray[i] = b.vArray[i];
}
}
int MyVector::size() const
{
return vSize;
}
int MyVector::capacity() const
{
return vCapacity;
}
void MyVector::clear(void)
{
if (vArray != nullptr)
{
delete[] vArray;
vArray = nullptr;
vSize = 0;
vCapacity = 0;
}
}
void MyVector::push_back(int n)
{
if (vCapacity == 0)
{
vCapacity++;
int* tmp = new int[vCapacity];
delete[] vArray;
vArray = tmp;
}
if (vSize >= vCapacity)
{
grow();
}
vArray[vSize] = n;
vSize++;
}
void MyVector::grow()
{
vCapacity = vCapacity + vCapacity;
int* tmp = new int[vCapacity];
for (int i = 0; i < vSize; i++)
{
tmp[i] = vArray[i];
}
delete[] vArray;
vArray = tmp;
}
int& MyVector::at(int index) const
{
if (index >= 0 && index<vSize)
{
return vArray[index];
}
else
{
throw index;
}
}
MyVector& MyVector::operator=(const MyVector& rho)
{
// test for self assignment
if (this == &rho)
return *this;
// clean up array in left hand object (this)
delete[] this->vArray;
// create a new array big enough to hold right hand object's data
vSize = rho.size();
this->vArray = new int[vSize];
// copy the data
for (int i = 0; i < rho.size(); i++)
{
this->vArray[i] = rho.vArray[i];
}
// return this object
return *this;
}
MyVector::~MyVector()
{
if (vArray != nullptr)
{
clear();
}
}
ostream& operator<<(ostream& out, const MyVector& rho)
{
for (int i = 0; i < rho.size(); i++)
{
out << rho.at(i);
}
return out;
}
Declare std::ostream& operator<<(std::ostream& out, const MyVector& rho) in My Vector.h. That function is used in Driver.cpp, therefore Driver.cpp must know about it.
If you do this, you should also #include <ostream> in My Vector.h.
To be able to use your offending operator<<() in main(), there needs to be a declaration of it visible to the compiler when compiling Driver.cpp.
That means you need to declare your operator<<() in MyVector.h.
Having the definition of operator<<() in MyVector.cpp is fine, but that is not visible to the compiler when compiling Driver.cpp
Related
I have a class strings:
class strings
{
protected:
string *ptr;
int size;
public:
strings() {
ptr = NULL;
size = -1;
}
strings(int size) {
this->size = size;
ptr = new string[size];
}
string* retPtr() {
return ptr;
}
void setPtr(int size)
{
ptr = new string[size];
this->size = size;
}
strings(const strings& obj) {
this->size = obj.size;
for (int i = 0;i < size;++i)
this->ptr[i] = obj.ptr[i];
}
friend istream& operator>>(istream& input, strings& obj) {
cin.ignore();
cout << "Enter " << obj.size << " string one by one:\n";
for (int i = 0;i < obj.size;++i)
{
getline(input, obj.ptr[i]);
}
return input;
}
friend ostream& operator<<(ostream& output, const strings& obj) {
cout << "Strings are:\n";
for (int i = 0;i < obj.size;++i)
output << obj.ptr[i] << "\n";
return output;
}
void operator =(const strings& obj)
{
this->size = obj.size;
for (int i = 0;i < size;++i)
ptr[i] = obj.ptr[i];
}
~strings()
{
delete[]ptr;
}
};
Another class stringsFromNumbers:
class stringsFromNumbers:public strings
{
int numbers;
public:
stringsFromNumbers(){
numbers = -1;
}
stringsFromNumbers(int size, int numbers):strings(size){
this->numbers = numbers;
}
stringsFromNumbers(const stringsFromNumbers& obj)
{
this->numbers = obj.numbers;
this->size = obj.size;
for (int i = 0;i < size;++i)
this->ptr[i] = obj.ptr[i];
}
friend istream& operator>>(istream& input, stringsFromNumbers& obj) {
cin.ignore();
cout << "Enter " << obj.size << " string one by one:\n";
for (int i = 0;i < obj.size;++i)
{
getline(cin, obj.ptr[i]);
}
return input;
}
friend ostream& operator<<(ostream& output, const stringsFromNumbers& obj) {
cout << "Numbers are: " << obj.numbers;
cout << "\nStrings are:\n";
for (int i = 0;i < obj.size;++i)
output << obj.ptr[i] << "\n";
return output;
}
void operator =(const stringsFromNumbers& obj)
{
this->numbers = obj.numbers;
this->size = obj.size;
for (int i = 0;i < size;++i)
this->ptr[i] = obj.ptr[i];
}
~stringsFromNumbers()
{
delete[] ptr;
}
};
Whenever i try execute this line of code:
stringsFromNumbers obj2(N, P);
where N and P are valid integers, I get an "Access Reading Violation", do you see something wrong in the code?
I have been stuck on this for almost 2 hours. I have tried debugging and fixing it, i have also tried multiple other methods. The exception takes me to this function:
inline void _Container_base12::_Orphan_all() noexcept {
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myproxy) { // proxy allocated, drain it
_Lockit _Lock(_LOCK_DEBUG);
for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) {
(*_Pnext)->_Myproxy = nullptr;
}
_Myproxy->_Myfirstiter = nullptr;
}
#endif // _ITERATOR_DEBUG_LEVEL == 2
}
The problem is with this function most probably but how can it be fixed?
stringsFromNumbers(int size, int numbers):strings(size){
this->numbers = numbers;
}
Both stringsFromNumbers::~stringsFromNumbers and strings::strings call delete[] on ptr, so the array is attempted to be freed twice; the second time causes an issue.
Only one of these classes should be responsible for managing the lifecycle of ptr. Remove the delete[] from stringsFromNumbers::~stringsFromNumbers.
If in some other case you've got a valid reason to free the array in the destructor of a subclass, make sure the parent class destructor is able to deal with the new state (e.g. by setting ptr to nullptr after deleting it), but in general you should avoid the complexity of making both classes sharing responsibility for freeing the memory.
I am defining my own string class called StringSet using a vector of strings. I am assigned to overload the >>, <<, ==, >, >=, +, += and * operators, and ran into a problem with <<. The output should be:
Welcome to stringset
hi everyone
"all" does not exist in the set.
hi
But it seems to be skipping the second and third lines. I am very new to overloading operators, so I am probably overlooking an obvious mistake.
header and class declaration:
#include <iostream>
#include <vector>
#include<string>
#include <iterator>
#include <algorithm>
#include <fstream>
using namespace std;
class StringSet
{
public:
//Constructor
StringSet();
//Copy Constructor
StringSet(const StringSet& s);
//Default constructors
StringSet(string initialStrings[], const int ARRAYSIZE);
//Destructor
~StringSet();
void add(const string s);
void remove(const string s);
//Returns length
int size()
{
return length;
}
// Overload the << operator so that it outputs the strings
friend ostream& operator <<(ostream& outs, const StringSet& s);
private:
//size of the vector
int length;
// Vector to store strings
vector <string> data;
};
function definitions:
ostream& operator<<(ostream& outs, const StringSet& s)
{
outs << "\n";
for (int i = 0; i < s.length; i++)
{
outs << s.data[i] << " ";
}
outs << "\n";
return outs;
}
//Add a string to the vector
void StringSet::add(const string s)
{
bool c = check(s);
if (c == false)
{
data.push_back(s);
}
else
{
cout << "\"" << s << "\" already exists in the set.";
}
}
// Remove a string from the vector
void StringSet::remove(const string s)
{
bool c = check(s);
if (c == true)
{
vector<string>::iterator position = search(s);
data.erase(position);
}
else
{
cout << "\"" << s << "\" does not exist in the set\n";
}
}
StringSet::StringSet()
{
length = 0;
}
StringSet::StringSet(string initialStrings[], const int ARRAYSIZE)
{
for (int i = 0; i < data.size(); i++)
{
initialStrings[i] = " ";
}
}
// Copy constructor
StringSet::StringSet(const StringSet& s)
{
for (int i = 0; i < data.size(); i++)
{
data[i] = s.data[i];
}
}
StringSet::StringSet()
{
length = 0;
}
StringSet::StringSet(string initialStrings[], const int ARRAYSIZE)
{
for (int i = 0; i < data.size(); i++)
{
initialStrings[i] = " ";
}
}
// Copy constructor
StringSet::StringSet(const StringSet& s)
{
for (int i = 0; i < data.size(); i++)
{
data[i] = s.data[i];
}
}
// Check if a string exists in the vector
bool StringSet::check(const string s)
{
vector<string>::iterator it = find(data.begin(), data.end(), s);
if (it != data.end())
{
return true;
}
else
{
return false;
}
}
Main function:
int main()
{
ofstream outs;
ifstream ins;
StringSet doc1, doc2, query
cout << "Welcome to stringset\n";
doc1.add("hi");
doc1.add("everyone");
outs << doc1;
doc1.remove("everyone");
doc1.remove("all");
outs << doc1;
}
If you use a variable that stores the size of the set, you should increment/decrement it when adding/removing elements. You can also change the definition of the StringSet::size():
int size() const
{
return static_cast<int>(data.size());
}
I made a dynamic array with template. The problem is that when I don't keep there pointers (for example: Tab<string> da;) my destructor doesn't have to clear it and throws error caused by delete arr[i];. My question is if I can put some if condition(in which I would put clear() method) which would tell me if my array keeps pointers. In the simplest way I can use clear() in main when I keeps there pointers, but my teacher wants me to make it like I wrote above.
I tried using is_pointer, but it doesn't work or I use it wrong.
Any suggestions?
#ifndef TABLICA_H
#define TABLICA_H
#include <iostream>
#include <type_traits>
using namespace std;
template<class T>
class Tab
{
public:
int size = 0;
int max_size = 1;
T* arr;
bool isDynamic = false;
Tab()
{
arr = new T[max_size];
}
~Tab()
{
clear();
delete[] arr;
}
void check_size()
{
if (size == max_size)
{
max_size = max_size * 2;
T* arr2 = new T[max_size];
for (int i = 0; i < size; i++)
{
arr2[i] = arr[i];
}
delete[] arr;
arr = arr2;
}
}
void push_back(const T& value)
{
check_size();
arr[size] = value;
size++;
}
T return_by_index(int index)
{
if (index<0 || index > size)
{
return NULL;
}
return arr[index];
}
bool replace(int index, const T& value)
{
if (index<0 || index > size)
{
return false;
}
arr[index] = value;
return true;
}
void print(int number)
{
cout << "Rozmiar obecny: " << size << endl;
cout << "Rozmiar maksymalny: " << max_size << endl;
cout << "Adres tablicy: " << arr << endl;
cout << "Kilka poczatkowych elementow tablicy " << "(" << number << ")" << endl;
for (int i = 0; i < number; i++)
{
cout << *arr[i] << endl;
}
}
void clear()
{
for (int i = 0; i < size; i++)
{
delete arr[i];
}
}
};
#endif
//Source:
#include <iostream>
struct object
{
int field1;
char field2;
object()
{
field1 = rand() % 10001;
field2 = rand() % 26 + 'A';
}
};
ostream& operator<<(ostream& out, const object& o)
{
return out << o.field1 << " " << o.field2;
}
int main()
{
Tab < object* >* da = new Tab < object* >();
delete da;
system("PAUSE");
return 0;
I'm trying to write code that implemets a template for a matrix with boundary check and additional operators. However, I'm stuck at a SIGGSEGV right now.
The matrix is based on a vector class I wrote myself, too:
#ifndef VEKTOR_H
#define VEKTOR_H
#include "Exeptions.h"
template<typename T>
class vektor
{
private:
unsigned int length;
T* items;
public:
inline unsigned int getLength() const{return length;};
vektor():length(0),items(nullptr)
{
//ctor
}
virtual ~vektor()
{
delete [] items;
}
vektor(const vektor& other):length(other.getLength()),items(new T[length])
{
for(int i = 0;i<length;i++)
{
items[i]=other[i];
}
}
vektor(int len):length(len),items(new T[len])
{
}
vektor<T>& operator=(const vektor& rhs)
{
if (this == &rhs) return *this; // handle self assignment
//assignment operator
length = rhs.getLength();
items = new T[length];
for(int i = 0;i<length;i++)
{
items[i]=rhs[i];
}
return *this;
}
T& operator[](const unsigned int index)const
{
if(index >= 0 && index < length)
{
return items[index];
}
else throw out_of_bounds();
}
};
#endif // VEKTOR_H
Then the code for the matrix:
#ifndef MATRIX_H
#define MATRIX_H
#include "vektor.h"
template <typename T>
class matrix
{
private:
int columns;
vektor<T>* tabs;
public:
inline int getColCount()const{return columns;};
inline int getRowCount()const{return tabs[0].getLength();};
inline vektor<T>* getTabs()const{return tabs;};
matrix():columns(0),tabs(new vektor<T>(0))
{
//ctor
}
matrix(int columns, int rows):columns(columns),tabs(new vektor<T>[columns])
{
for(int i = 0; i< columns;i++)
{
tabs[i] = *new vektor<T>(rows);
}
}
virtual ~matrix()
{
delete tabs;
}
matrix(const matrix& other):rows(other.getColCount()),tabs(new vektor<T>(*other.getTabs()))
{
//copy ctor
}
matrix<T>& operator=(const matrix& rhs)
{
if (this == &rhs) return *this; // handle self assignment
//assignment operator
spalten = rhs.getColCount();
tabs = new vektor<T>(*rhs.getTabs());
return *this;
}
vektor<T>& operator[](unsigned int index)
{
return tabs[index];
}
};
#endif // MATRIX_H
A wrapper class that instantiates a matrix with string to create a menu-like structure:
MenUI::MenUI():selectedTab(3),selectedItem(4),menItems(matrix<string>(3,4))
{
menItems[0][0] = "File";
menItems[0][1] = "Edit";
menItems[0][2] = "View";
menItems[0][3] = "Search";
menItems[1][0] = "New";
menItems[1][1] = "Undo";
menItems[1][2] = "Perspectives";
menItems[1][3] = "Find";
menItems[2][0] = "Open...";
menItems[2][1] = "Redo";
menItems[2][2] = "Toolbars";
menItems[2][3] = "Find in Files";
}
And here the SIGSEGV happens at line tmp = menItems[selectedTab][i];
void MenUI::print()
{
int offset = 0;
string tmp;
for(unsigned int i = 0; i<menItems.getColCount();i++)
{
tmp = menItems[i][0];
if (i == selectedTab) cout << "|- " << setw(10) << tmp << " -";
else cout << "| " << setw(10) << tmp << " ";
}
cout << "|" << endl;
offset = selectedTab * (10 + 5);
for(unsigned int i = 1;i<menItems.getRowCount();i++)
{
tmp = menItems[selectedTab][i];
if(i == selectedItem) cout << string(offset-3, ' ') << "|> " << setw(10) << tmp << " <|" << endl;
else cout << string(offset-3, ' ') << "| " << setw(10) << tmp << " |" << endl;
}
}
As this is the first time I used templates, I'm a bit lost right now.
I'm using Code::Blocks IDE with GCC.
It would be really great if someone could point me in the right direction.
Thanks!
If selectedTab is 3 and you do tmp = menItems[selectedTab][i]; your code will seg fault because you are accessing outside the bounds of the memory.
I might have taken what you have written too literally and you change selectedTab
I am receiving a runtime error from code I have written. When I call the grow() function it works perfectly until it hits the delete, then it crashes and says:
This really confuses me and I do not understand what is going on with that.
Here is my code where it is happening:
The .cpp File
#include "MyVector.h"
#include <cstdlib>;
void MyVector::grow()
{
if (cap == 0)
cap = MINCAP;
else
cap = cap*MINCAP;
int* temp = new int[cap];
for (int i = 0; i < vectorSize; i++)
{
temp [i] = theVector[i];
}
for (int i = vectorSize; i < cap; i++)
{
temp[i] = 0;
}
delete[] theVector;
theVector = temp;
}
MyVector::MyVector()
{
clear();
}
MyVector::~MyVector()
{
delete[] this->theVector;
}
MyVector::MyVector(int _cap)
{
cap = _cap;
for (int i = 0; i < cap; i++)
{
this->theVector[i] = 0;
}
}
MyVector::MyVector(const MyVector & vect)
{
this->vectorSize = vect.vectorSize;
this->cap = vect.cap;
delete[] theVector;
theVector = new int[cap];
for (int i = 0; i < vectorSize; i++)
{
this->theVector[i] = vect.theVector[i];
}
for (int i = vectorSize; i < cap; i++)
{
this->theVector[i] = 0;
}
}
int MyVector::size() const
{
return vectorSize;
}
int MyVector::capacity() const
{
return cap;
}
void MyVector::clear()
{
vectorSize = 0;
cap = MINCAP;
delete[] theVector;
theVector = new int[MINCAP];
for (int i = 0; i <MINCAP; i++)
{
*(theVector + i) = 0;
}
}
//Put an int into the vector
void MyVector::push_back(int n)
{
if (theVector == nullptr)
clear();
if (vectorSize+1 >= cap)
{
grow();
theVector[vectorSize] = n;
vectorSize++;
}
else
{
theVector[vectorSize] = n;
vectorSize++;
}
}
int MyVector::at(int _location)
{
if (_location < 0 || _location >= vectorSize)
throw _location;
return theVector[_location];
}
MyVector & MyVector::operator=(const MyVector & rho)
{
// test for self assignment
if (this == &rho)
return *this;
// clean up array in left hand object (this)
delete[] this->theVector;
// create a new array big enough to hold right hand object's data
this->vectorSize = rho.size();
this->cap = rho.cap;
this->theVector = new int[cap];
// copy the data
for (int i = 0; i < vectorSize; i++)
{
this->theVector[i] = rho.theVector[i];
}
for (int i = vectorSize; i < cap; i++)
{
this->theVector[i] = 0;
}
// return this object
return *this;
}
The.h File
#pragma once
#include <array>
#include <fstream>
using namespace std;
class MyVector
{
private:
//the minimum capacity of the vector
const int MINCAP = 2;
//the amount of items in the vector
int vectorSize = 0;
//the maximum ammount of items in the vector
int cap = MINCAP;
//The pointer to the first integer in the vector
int* theVector = new int[MINCAP];
//The grow function
//Parameters : none
//returns : none
void grow();
public:
//The nonparmeterized constructor
//Parameters : none
//returns :none
MyVector();
//The deconstructor
//Parameters : none
//returns : none
~MyVector();
// The parameterized constructor
//Parameters : the capacity to set it to
//returns : none
MyVector(int _cap);
//Get the size
//Parameters : none
//returns : the size
MyVector(const MyVector& vect);
//Get the size
//Parameters : none
//returns : the size
int size() const;
//get the capacity
//Parameters : none
//returns : cap
int capacity() const;
//clear the data
//Parameters : none
//returns :none
void clear();
//insert an int into the vector
//Parameters : the int
//returns : none
void push_back(int n);
//gets the int at a location
//Parameters : the location
//returns : the integer
int at(int _location);
//Overload the = operator
//Parameters : the one to copy
//returns : the vector
MyVector& operator=(const MyVector& rho);
//Overload the << operator
//Parameters : the one to copy
//returns : the vector
friend ostream& operator<<(ostream& os, MyVector& TheVector)
{
for (int i = 0; i < TheVector.size(); i++)
{
os << TheVector.at(i) << ", ";
}
return os;
}
};
The driver to test it.
#include <iostream>
#include "MyVector.h"
using namespace 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;
}
EDIT: I updated the code with the recommendations.
There are a few problems with your code:
your MyVector(int) constructor does not allocate the requested number of array elements. It is not even touching theVector at all, so theVector is being member-initialized to the default of MINCAP elements, even if the requested cap is actually higher.
your MyVector(MyVector&) copy constructor is declared wrong. To be a proper copy constructor, it needs to take the input object by const reference instead. Without that, you do not have a proper copy constructor. If the compiler generates its own default copy constructor, it will simply copy your theVector pointer from one object to another and not actually make a new copy of the array data, thus causing ownership problems.
case in point, your printV() function takes an input MyVector by value, which copy-constructs a temporary object. When the temporary goes out of scope and calls delete[] on its theVector pointer, it is actually going to destroy the array in the original MyVector object if the compiler's default copy constructor is used. You need a proper copy constructor.
clear() is using delete instead of delete[]. Memory allocated with new must be freed with delete. Memory allocated with new[] must be freed with delete[]. Mismatching them can cause memory problems.
With that said, I would suggest the following implementation:
#pragma once
#include <iostream>
class MyVector
{
private:
//the minimum capacity of the vector
const int MINCAP = 2;
//the number of items in the vector
int vectorSize = 0;
//the maximum number of items in the vector
int cap = 0;
//The pointer to the first integer in the vector
int* theVector = nullptr;
//The grow function
//Parameters : none
//returns : none
void grow();
public:
//The nonparmeterized constructor
//Parameters : none
//returns :none
MyVector();
// The parameterized constructor
//Parameters : the capacity to set it to
//returns : none
MyVector(int _cap);
// The copy constructor
//Parameters : the vector to copy from
//returns : none
MyVector(const MyVector& src);
// The move constructor
//Parameters : the vector to move from
//returns : none
MyVector(MyVector&& src);
//The destructor
//Parameters : none
//returns : none
~MyVector();
//Get the size
//Parameters : none
//returns : the size
int size() const;
//get the capacity
//Parameters : none
//returns : cap
int capacity() const;
//clear the data
//Parameters : none
//returns :none
void clear();
//insert an int into the vector
//Parameters : the int
//returns : none
void push_back(int n);
//gets the int at a location
//Parameters : the location
//returns : the integer
int at(int _location);
//swap the content of a vector with another
//Parameters : the vector to swap with
//returns : none
void swap(MyVector& other);
//Overload the copy = operator
//Parameters : the one to copy from
//returns : the vector
MyVector& operator=(const MyVector &rho);
//Overload the move = operator
//Parameters : the one to move from
//returns : the vector
MyVector& operator=(MyVector && rho);
//Overload the << operator
//Parameters : the one to print
//returns : the stream
friend std::ostream& operator<<(std::ostream& os, const MyVector& rho);
};
std::ostream& operator<<(std::ostream& os, const MyVector& rho);
void swap(MyVector &v1, MyVector &v2) { v1.swap(v2); }
namespace std {
template <>
void swap(MyVector &v1, MyVector &v2)
{
v1.swap(v2);
}
}
#include "MyVector.h"
#include <algorithm>
#include <utility>
MyVector::MyVector()
: MyVector(MINCAP)
{
}
MyVector::MyVector(int _cap)
: theVector(new int[_cap]), cap(_cap)
{
std::fill_n(theVector, cap, 0);
}
MyVector::MyVector(const MyVector & src)
: theVector(new int[src.cap]), cap(src.cap), vectorSize(src.vectorSize)
{
std::copy_n(src.theVector, vectorSize, theVector);
std::fill_n(theVector+vectorSize, cap-vectorSize, 0);
}
MyVector::MyVector(MyVector && src)
{
src.swap(*this);
}
MyVector::~MyVector()
{
delete[] theVector;
}
void MyVector::grow()
{
int newcap = cap;
if (newcap == 0)
newcap = MINCAP;
else
newcap = newcap * MINCAP;
int* newVector = new int[newcap];
std::copy_n(theVector, vectorSize, newVector);
std::fill_n(newVector+vectorSize, newcap-vectorSize, 0);
delete[] theVector;
theVector = newVector;
cap = newcap;
}
int MyVector::size() const
{
return vectorSize;
}
int MyVector::capacity() const
{
return cap;
}
void MyVector::clear()
{
*this = MyVector();
}
void MyVector::push_back(int n)
{
if (vectorSize >= cap)
grow();
theVector[vectorSize] = n;
++vectorSize;
}
int MyVector::at(int _location)
{
if ((_location < 0) || (_location >= vectorSize))
throw _location;
return theVector[_location];
}
void MyVector::swap(MyVector& other)
{
std::swap(theVector, other.theVector);
std::swap(cap, other.cap);
std::swap(vectorSize, other.vectorSize);
}
MyVector& MyVector::operator=(const MyVector &rho)
{
if (this != &rho)
{
int newcap = rho.cap;
if (cap != newcap)
{
delete[] theVector;
theVector = nullptr;
cap = 0;
vectorSize = 0;
theVector = new int[newcap];
cap = newcap;
}
int newsize = rho.vectorSize;
std::copy_n(rho.theVector, newsize, theVector);
std::fill_n(theVector+newsize, cap-newsize, 0);
vectorSize = newsize;
}
return *this;
}
MyVector& MyVector::operator=(MyVector && rho)
{
rho.swap(*this);
return *this;
}
std::ostream& operator<<(std::ostream& os, const MyVector& rho)
{
os << "size " << rho.vectorSize << ", capacity " << rho.cap;
if (rho.vectorSize > 0)
{
os << "\n" << rho.theVector[0];
for (int i = 1; i < rho.vectorSize; ++i)
{
os << ", " << rho.theVector[i];
}
}
return os;
}
#include <iostream>
#include "MyVector.h"
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(MyVector);
int main()
{
std::cout << "\nCreating a vector Sam of capacity 4.";
MyVector sam(4);
std::cout << "\nPush 12 values into the vector.";
for (int i = 0; i < 12; ++i)
sam.push_back(i);
std::cout << "\nHere is sam: ";
std::cout << sam;
std::cout << "\n---------------\n";
std::cout << "\nCreating a vector Joe of capacity 4.";
MyVector joe(4);
std::cout << "\nPush 6 values into the vector.";
for (int i = 0; i < 6; ++i)
joe.push_back(i * 3);
std::cout << "\nHere is joe: ";
std::cout << joe;
std::cout << "\n---------------\n";
std::cout << "\nTest the overloaded copy assignment operator \"joe = sam\": ";
joe = sam;
std::cout << "\nHere is sam: ";
std::cout << sam;
std::cout << "\n---------------\n";
std::cout << "\nHere is joe: ";
std::cout << joe;
std::cout << "\n---------------\n";
std::cout << "\nTest the overloaded move assignment operator \"joe = MyVector(5)\": ";
joe = MyVector(5);
std::cout << "\nHere is joe: ";
std::cout << joe;
std::cout << "\n---------------\n";
// pass a copy of sam by value
printV(sam);
std::cout << std::endl;
system("PAUSE");
return 0;
}
void printV(MyVector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}