C++ Operator overload calling destructor - c++

For my first try with operator overloading I created a vector class and tried to sum up two vectors. My class contains an array and a vector of int that both contain the same elements.
Addition works fine with the std::vector but I encounter two issues with the array. It seems that the destructor is called at the end of the summing operation which produces a "double free or corruption" error (core dump). Plus, the first two elements of the array are always equal to zero.
Should I also overload the delete or am I missing a thing ?
The header file:
#ifndef MYVECTOR_INCLUDE
#define MYVECTOR_INCLUDE
#include <iostream>
#include <stdexcept>
#include <cstring>
#include <vector>
class MyVector {
public:
MyVector(int n);
~MyVector();
void set(int idx, int value);
int get(int idx);
void print();
MyVector &operator=(const MyVector &v);
MyVector operator+(const MyVector &v);
private:
int *data;
std::vector<int> data_vector;
int size1;
int size2;
};
#endif
The cpp file:
#include "../include/myvector.hpp"
MyVector::MyVector(int n) {
data = new int [n];
data_vector.resize(n);
size1 = n;
size2 = 1;
}
MyVector::~MyVector() {
if (data != NULL) {
delete [] data;
}
}
void MyVector::set(int idx, int value) {
data_vector[idx] = value;
data[idx] = value;
}
int MyVector::get(int idx) {
return data_vector[idx];
}
void MyVector::print() {
std::cout << "Vector data" << std::endl;
for (int i = 0; i < size1; ++i) {
std::cout << data_vector[i] << " ";
}
std::cout << std::endl;
std::cout << "Data" << std::endl;
for (int i = 0; i < size1; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
MyVector &MyVector::operator=(const MyVector &v) {
if (this == &v)
return *this;
size1 = v.size1;
size2 = v.size2;
std::copy(v.data_vector.begin(), v.data_vector.end(), data_vector.begin());
memcpy(&data, v.data, sizeof(int)*size1);
return *this;
}
MyVector MyVector::operator+(const MyVector &v) {
if ((size1 == v.size1) && (size2 == v.size2)) {
MyVector res = MyVector(size1);
for (int i = 0; i < size1; ++i) {
res.data_vector[i] = data_vector[i] + v.data_vector[i];
res.data[i] = data[i] + v.data[i];
}
return res;
}
else
throw std::length_error("Vector dimensions must agree.");
}
Thank you.

See the rule of three/five/zero.
The rule of three states
If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.
In this case, you provided the destructor and copy assignment operator but forgot the copy constructor.
In operator+ you create a local object MyVector res which is later copied out and then destroyed. Since you haven't implemented a copy constructor, the default copy constructor will simply copy the original data pointer from res to another MyVector. When res is destroyed, the array pointed to by it's data member will be deleted, leaving the copied vector's data pointing to a deleted object.

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;
}

Returning an object in c++ by reference

The goal I set to myself is to overload operator+ (adding class objects). It turns out that this sum can be just interpreted as the sum of two vectors. But when it comes to the method operator+, I find it difficult to return the object. I've read similar topics and even try to apply some sugestions but with no success, unfortunatelly. I enclose some of my code.
template<class Y>
class myVect {
public:
myVect(int n = 1);
~myVect();
myVect(const myVect& a);
myVect& operator= (const myVect&);
myVect& operator+ (const myVect&);
void display(const myVect& a);
private:
int size;
Y* data;
template<class U> friend class myClass;
};
template<class Y> // constructor
myVect<Y>::myVect(int n) {
size = n;
data = new Y[size];
cout << endl << "Pass the elements" << " " << size << "\n";
for (int i = 0; i < size; i++) {
cin >> *(data + i);
}
}
template <class Y> // deconstructor
myVect<Y> :: ~myVect() {
delete[] data;
}
template<class Y> // copy constructor
myVect<Y> ::myVect(const myVect & a) {
size = a.size;
data = new Y[size];
for (int i = 0; i < size; i++) {
*(data + i) = *(a.data + i);
}
}
template<class Y> //ASSIGMENT OPERATOR
myVect<Y> & myVect<Y> :: operator= (const myVect<Y> & a) {
if (this != &a) {
delete[] data;
size = a.size;
data = new Y[size];
for (int i = 0; i < size; i++) {
*(data + i) = *(a.data + i);
}
}
return *this;
}
The method operator+ is a follows:
template<class Y>
myVect<Y>& myVect<Y> ::operator+ (const myVect<Y>& a) {
if (this->size != a.size) {
cout << endl << "not able to perform that operation - wrong dimensions" << endl;
}
else {
myVect<Y> newObj(this->size);
for (int i = 0; i < this->size; i++) {
*(newObj.data + i) = *(this->data + i) + *(a.data + i);
}
}
return newObj;
}
The error I get is 'newObj': identifier not found. I believe it's due to deconstructor. I tried to put the class myVect into a new class (encapsulate it) and contruct the return method but it didn't change antything - the type of the error is still the same. Do you know how to solve this problem?
Anyway, if it is the destructor fault, does that mean that newObj is deleted before its return?
The problem can be reduced to this:
int foo()
{
if (true) // In reality, some meaningful condition
{
int x = 4;
}
return x;
}
The variable is scoped to the if block. It doesn't exist outside of it.
You'll have to move its declaration out of the conditional, and do whatever else is required to make that work… or return from inside the condition, and do something else (throw an exception?) otherwise.
For example, given the above demonstration:
int foo()
{
int x = 0; // Or some other value
if (true) // In reality, some meaningful condition
{
x = 4;
}
return x;
}
or:
int foo()
{
if (true) // In reality, some meaningful condition
{
int x = 4;
return x;
}
throw std::runtime_error("For some reason I have no value to give you!");
}
Your next problem will be that you are trying to return a local variable by reference. You cannot do that. Return it by value instead, which is anyway idiomatic for what you're doing.
You've declared your object inside of a block, so it won't exist in the outside scope. This would normally free you up to reuse variable names across different branches; try making a newObj inside the if part of the statement and watch it not throw an error, for example.

Is my destructor giving me this error: *** Error in `./main': double free or corruption (fasttop):?

This is the instructions for my assignment:
The Copy Constructor. The copy constructor should perform a deep copy of the argument object, i.e. it should construct an IntCollection with the same size and capacity as the argument, with its own complete copy of the argument's data array.
The Assignment Operator (=). The assignment operator should also perform a deep copy of the argument object. It must return itself (or more efficiently, a reference to itself) in order tosupport multiple assignments on the same line, e.g. a = b = c. If you implement your assignment operator first it could be used in the copy constructor, but this is not a requirement.
The Is Equals operator (==). The "is equals" operator should return true if the argument object has the same size as the receiving object, and the values in both objects’ data arrays are identical.
The insertion operator (<<). The insertion operator should add the int parameter into the receiving IntCollection. The functionality is exactly the same as the add() function, i.e. add ints to the collection. Note, however, that this function must return a reference to itself in order to support multiple insertions on the same line, e.g. c << 45 << -210. Unlike the assignment operator, this return must be done by reference, because each insertion actually modifies the IntCollection object, and insertion is done from left to right.
The destructor. Function add() calls addCapacity() to allocate memory when it needs more room. Nowhere in this program is the memory deallocated with delete [], which means we have a memory leak! Add a destructor which correctly handles this.
addCapacity. Note that addCapacity() is a private member function. What happens if you try to call it from outside the class, i.e. by adding the line below to main()?
c.addCapacity();
Here is my code:
IntCollection.h:
#ifndef INTCOLLECTION_H
#define INTCOLLECTION_H
// Allocate memory in chunks of ints of this size.
const int CHUNK_SIZE = 5;
class IntCollection
{
private:
// The number of ints currently stored in the int
int size;
// the total number of elements available for storage
// in the data array
int capacity;
// A pointer to the dynamically allocated data array
int* data;
// a private member function to allocate more memory
// if necessary
void addCapacity();
public:
// Constructor
IntCollection();
// Destructor
~IntCollection();
// Copy constructor:
IntCollection(const IntCollection &c);
void add(int value);
int get(int index);
int getSize();
IntCollection& operator=(const IntCollection &c);
bool operator==(const IntCollection &c);
IntCollection& operator<<(int value);
};
#endif
IntCollection.cpp:
#include "IntCollection.h"
#include <cstdlib>
#include <iostream>
using namespace std;
IntCollection::IntCollection()
{
// Initialize member data to reflect an empty
// IntCollection
size = capacity = 0;
data = NULL;
}
IntCollection::~IntCollection()
{
delete [] data;
}
IntCollection::IntCollection(const IntCollection &c) {
size = c.size;
capacity = c.capacity;
data = c.data;
for (int i = 0; i < c.size; i++)
{
data[i] = c.data[i];
}
}
void IntCollection::addCapacity()
{
// Create a new, bigger buffer, copy the current data to
// it, delete the old buffer, and point our data
// pointer to the new buffer
int *newData;
data = new int[capacity];
capacity += CHUNK_SIZE;
newData = new int[capacity];
for (int i = 0; i < size; i++)
{
newData[i] = data[i];
delete[] data;
data = newData;
}
}
void IntCollection::add(int value)
{
// first, allocate more memory if we need to
if (size == capacity)
{
addCapacity();
}
// Now, add the data to our array and increment size
data[size++] = value;
}
int IntCollection::get(int index)
{
if (index < 0 || index >= size)
{
cout << "ERROR: get() trying to access index out of range.\n";
exit(1);
}
return data[index];
}
int IntCollection::getSize()
{
return size;
}
IntCollection &IntCollection::operator=(const IntCollection &c)
{
size = c.size;
capacity = c.capacity;
data = c.data;
return *this;
}
bool IntCollection::operator==(const IntCollection &c)
{
if ((size == c.size) && (capacity == c.capacity))
{
for (int m = 0; m < size; m++)
{
if (data[m] == c.data[m])
{
continue;
} else
{
return false;
}
}
}
return true;
}
IntCollection &IntCollection::operator<<(int value)
{
add(value);
return *this;
}
main.cpp:
#include "IntCollection.h"
#include <iostream>
using namespace std;
int main()
{
IntCollection c;
c.add(45);
c.add(-210);
c.add(77);
c.add(2);
c.add(-21);
c.add(42);
c.add(7);
for (int i = 0; i < c.getSize(); i++)
{
cout << c.get(i) << endl;
}
IntCollection d(c);
for (int i = 0; i < c.getSize(); i++)
{
cout << c.get(i) << endl;
}
IntCollection e;
e = c;
cout << "Testing = Overload" << endl;
for(int i = 0; i < c.getSize(); i++)
{
cout << c.get(i) << endl;
}
IntCollection f;
f<<8<<9<<10;
cout << "Testing<<Overload" << endl;
for(int i = 0; i < f.getSize(); i++)
{
cout << f.get(i) << endl;
}
cout << "Testing == Overload" << endl;
c.add(10);
if(f == c)
{
cout << "Both objects match" << endl;
}
else
{
cout << "They don't match" << endl;
}
return 0;
}
After I believed that I fixed most of my errors, I get this as my output:
*** Error in `./main': double free or corruption (fasttop): 0x0000000000b2ec80 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7ff7e6f70bfb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76fc6)[0x7ff7e6f76fc6]
/lib/x86_64-linux-gnu/libc.so.6(+0x7780e)[0x7ff7e6f7780e]
./main[0x400fa1]
./main[0x400fe2]
./main[0x400aa2]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7ff7e6f202e1]
./main[0x40097a]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:01 11008976 /home/runner/main
I won't post all of it because it is long. Is my destructor causing this? I am not sure how to fix this nor have I ever encountered this error before.
This line, from your copy constructor, is the likely problem:
data = c.data;
After that line, you have two object pointing to the same data. It is a shallow copy.
If one of the objects are destructed then if will delete[] the data, leaving the other object with an invalid pointer. When the second objects destructor then tries to delete[] the data (again!) it will lead to undefined behavior.
You need to do a deep copy, which is the assignment you have. That includes a new memory allocation and actually copying the data.
Same thing with the copy-assignment operator.

can't return pointer in class [duplicate]

This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 8 years ago.
#include "C_IntArray.h"
C_IntArray::C_IntArray()
{
m_Array = 0;
m_Length = 0;
}
C_IntArray::~C_IntArray(void)
{
delete m_Array;
m_Length = 0;
}
void C_IntArray::ContructorWithParater(int *intArray, int size)
{
m_Array = new int[size];
m_Length = size;
for (int i = 0; i < size; i++)
m_Array[i] = intArray[i];
}
void C_IntArray::InputArray()
{
cout << "Nhap so luong phan tu: ";
cin >> m_Length;
m_Array = new int [m_Length];
for(int i = 0; i < m_Length; i++)
{
cout << "Nhap phan tu Array[" << i << "] = ";
cin >> m_Array[i];
}
}
void C_IntArray::OutputArray()
{
for(int i = 0; i < m_Length; i++)
cout << m_Array[i] << " ";
}
C_IntArray C_IntArray::Remove(int x)
{
C_IntArray temp;
temp.ContructorWithParater(m_Array, m_Length);
temp.OutputArray();
for(int i = 0; i < temp.m_Length; i++)
{
if(temp.m_Array[i] == x)
{
{
temp.m_Length--;
for(int j = i; j < temp.m_Length; j++)
temp.m_Array[j] = temp.m_Array[j + 1];
}
}
cout << "\n";
temp.OutputArray();
}
cout << "\n";
return temp;
}
File Header
#include <iostream>
using namespace std;
#ifndef _C_IntArray_h
#define _C_IntArray_h
class C_IntArray
{
private:
int *m_Array, m_Length;
public:
C_IntArray();
~C_IntArray();
// khoi tao tham so dau vao
void ContructorWithParater(int *, int);
void InputArray();
void OutputArray();
// xoa phan tu trung
C_IntArray Remove(int );
};
#endif _C_IntArray_h;
File main
#include "C_IntArray.h"
void main()
{
C_IntArray a;
a.InputArray();
int giaTriCanXoa = 5;
C_IntArray b = a.Remove(giaTriCanXoa);
b.OutputArray();
cout << "\n";
a.OutputArray();
system("pause");
}
i have tried to debug my project. the function Remove in class is work, and when i'm debug to return temp it still work, but i'm debug next it return NULL or return 1 array
function Remove in class can't return temp.
if i remove destructor or my temp is static C_IntArray, my project can run.
if I have misspelled the desire to help people fix.
thank you for the attention.
Remove returns a copy of the class, not a pointer. Therefore it is a copy.
Since you do not define a copy constructor or an assignment operator then you'll be using the default copy/assign - which will result in m_Array being deleted more than once.
You can either perform a deep copy of the internal array when copying the class or use Copy on Write and reference counting.
i.e. you will need to add the following functions:
C_IntArray(C_IntArray const& other);
C_IntArray& operator=(C_IntArray const& rhs);
They should allocate new storage for the data in the array and copy the elements from 'other' or 'rhs'. Look up how to write a copy constructor or assignment operator. There will be countless examples online.
There are also memory leaks in your class.
C_IntArray::InputArray() will leak memory since you do not delete m_Array before assigning new memory to it.
It would be better to use a free function for input duties rather than making it a class member - keep the interface of your class minimal and complete.
i.e. move it out of the class:
void InputArray(C_IntArray& dst) {
// ...
}
As others have suggested, just use std::vector.

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()
{
}