What happens in each scenario and how is this accomplished? - c++

I have a Stack class defined. Now, I want to reverse the stack by passing it to a reverseStack function. I want to know what happens in various scenarios. And finally, what is the best way to do it.
STACK IMPLEMENTATION:
class Stack {
public:
Stack() {
a = new int[25];
capacity = 25;
}
Stack(int size) {
a = new int[size];
capacity = size;
}
~Stack() {
delete[] a;
}
void push(int x) {
if (index == capacity - 1) {
cout << "\n\nThe stack is full. Couldn't insert " << x << "\n\n";
return;
}
a[++index] = x;
}
int pop() {
if (index == -1) {
cout << "\n\nNo elements to pop\n\n";
return -1;
}
return a[index--];
}
int top();
bool isEmpty();
void flush();
private:
int capacity ;
int* a;
int index = -1; // Index of the top most element
};
SCENARIO-1:
void reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
s = s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
reverseStack(s);
return 0;
}
SCENARIO-2:
Stack reverseStack(Stack& s) {
Stack s2;
while (!s.isEmpty()) {
s2.push(s.pop());
}
return s2;
}
int main() {
Stack s;
s.push(1);
s.push(2);
s.push(3);
s = reverseStack(s);
return 0;
}
In Scenario-1 (which fails), what does s = s2 inside the function mean? I think it's a member-wise copy. Would it have worked if the data members didn't involve a pointer (int* a)?
Scenario-2 fails as well for the same reason. How do I accomplish what I'm trying to?
Should I have a copy-constructor (and how do I implement it?). How about overloading the assignment operator (again, how do I implement?) ?
I tried to implement it this way:
Stack Stack::operator = (Stack s) {
capacity = s.capacity;
int* a = new int[capacity];
for (int i = 0; i < capacity; i++) {
a[i] = s.a[i];
}
index = s.index;
return *this;
}

About the scenarios, the best one is the second because of the return value optimization, i.e: The compiler will probably optimize away the copy of the return value and prevent an unnecessary copy.
Now, you are using dynamic memory in your class, which means the default implementation of the copy constructor and assignment operator will not work for you.
Copy constructor, it's almost the same as the assignment operator you write
Stack::Stack(const Stack& s)
: capacity(s.capacity)
, a(new int[capacity])
, index(s.index)
{ // std::copy is just a shortcut, what you're doing is fine too
std::copy(s.a, s.a + capacity, a);
}
The assignment operator you wrote is wrong in two ways:
It should return a Stack object by reference
The parameter should be a const reference
The rest is just ok
Stack& Stack::operator = (const Stack& s) {
capacity = s.capacity;
a = new int[capacity];
for (int i = 0; i < capacity; i++) { // or std::copy
a[i] = s.a[i];
}
index = s.index;
return *this;
}
Update
Tentative implementation of the reverseStack function (without side-effects), assuming index contains the actual number of items in the stack
Stack reverseStack(const Stack& s) {
Stack s2(s.capacity);
for (int i = 0; i < s2.index; ++i) {
s2.a[i] = s2.a[s2.index -i];
}
return s2;
}
Update Thanks to user657267 from pointing out int* a = new int[capacity]; was wrong

Related

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.

Overloading addition operator (adding a string to an object using a function)

I'm creating a dynamic array class and I'm new to c++. I'm having trouble overloading the addition operator to add a string to an object. When I do try to add a string, nothing shows up on the compile screen. I also added my copy constructor, destructor, overloaded assignment operator, and overloaded ostream operator just in case any of those were the issue. Thank you so much for the help!!
DynamicStringArray::~DynamicStringArray()
{
delete[] dynamic_Array;
dynamic_Array = NULL;
}
DynamicStringArray::DynamicStringArray(const DynamicStringArray& first)
{
size = first.returns_Size();
dynamic_Array = new string[size];
for (int n = 0; n < size; n++)
{
dynamic_Array[n] = first.get_Entry(n);
}
}
void DynamicStringArray::operator =(const DynamicStringArray& first)
{
this->size = first.returns_Size();
this->dynamic_Array = new string[size];
for (int i = 0; i < this->size; i++)
{
this->dynamic_Array[i] = first.get_Entry(i);
}
}
ostream& operator <<(ostream& out, const DynamicStringArray& first) //nonmember requires 2 arguments
{
for (int i = 0; i < first.size; i++)
{
out << first.dynamic_Array[i] << endl;
}
return out;
}
void DynamicStringArray::add_Entry(string a)
{
string* Temp_Array = dynamic_Array; //old array
dynamic_Array = new string[size + 1]; //new array
for (int i= 0; i < size; i++) //copy old string values to temp array
{
dynamic_Array[i] = Temp_Array[i];
}
dynamic_Array[size] = a; //puts string a into last position of new array
delete[]Temp_Array; //free memory space
size++;
}
DynamicStringArray DynamicStringArray::operator +(const string& a)
{
DynamicStringArray added;
added.add_Entry(a);
return added;
}
int main()
{
DynamicStringArray fav_Foods;
fav_Foods.add_Entry("pasta");
fav_Foods.add_Entry("sushi");
fav_Foods + "Burgers";
cout << fav_Foods << endl;
}
DynamicStringArray DynamicStringArray::operator +(const string& a)
{
DynamicStringArray added;
added.add_Entry(a);
return added;
}
Why do you think you need to create a new DynamicStringArray added?
Simply call add_Entry(a) on the current instance. Also, operator+() should return a reference to the instance it is called upon:
DynamicStringArray& DynamicStringArray::operator+(string const &a)
{
add_Entry(a);
return *this;
}

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.

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

How do you copy an object of a class to another object of the same class by using '='

How do you copy an object of a class to another object of the same class just by using '='. I know that we have to overload the operator. here's what I have so far
#include<iostream>
#include<conio.h>
#include<iomanip>
using namespace std;
class arr
{
public:
int *arr1;
int len;
arr& operator = (const arr& eq) //for copying two arrays. <--- my overloader
{
arr temp1(eq.len);
arr *pttemp;
int i=0;
//temp.arr1=new int[eq.len];
//temp.len = eq.len;
for(i = 0 ; i < eq.len ; i++)
{
temp1.arr1[i] = eq.arr1[i];
}
pttemp = &temp1;
return temp1;
};
friend istream& operator >> (istream& ist, arr & r)
{
static int i = 0;
int *arrNew;
if (i == r.len)
{
r.len *=2;
arrNew = new int[r.len]; // allocate the new array
for(int j = 0; j < r.len/2; j++)// copy the old array to the first half of the new array
arrNew[j] = r.arr1[j];// delete the old array
delete [] r.arr1;// let arr point to the new array and continue use arr
r.arr1 = arrNew;
delete arrNew;
}
ist>>r.arr1[i];
i++;
return ist;
}
arr() //initializing constructor
{
len = 5;
arr1 = new int[len];
};
arr(int size) //initializing constructor with args
{
len = size;
arr1 = new int[len];
};
arr(arr& a) : arr1(a.arr1) //copy constructor
{
arr1 = new int[len];
};
~arr() //delete constructor
{
delete arr1;
};
};
void main()
{
int size = 5,i,temp,trig = 0;
arr orig(size), asc(size), desc(size);
//generate random numbers for orig
for (i = 0 ; i < size ; i++)
{
orig.arr1[i] = rand();
}
//copy original set to asc and desc
asc = orig;
desc = orig;
//sorting ascending
for (i = 0 ; i < size-1 ; i++)
{
trig = 1;
if (asc.arr1[i] < asc.arr1[i+1])
{
temp = asc.arr1[i];
asc.arr1[i] = asc.arr1[i+1];
asc.arr1[i+1] = temp;
trig = 0;
}
if (trig = 1)
break;
if (i == size - 1)
{
i = 0;
}
}
//sorting descending
for (i = 0 ; i < size-1 ; i++)
{
trig = 1;
if (desc.arr1[i] > desc.arr1[i+1])
{
temp = desc.arr1[i];
desc.arr1[i] = desc.arr1[i+1];
desc.arr1[i+1] = temp;
trig = 0;
}
if (trig = 1)
break;
if (i == size - 1)
{
i = 0;
}
}
//printing
cout<<"Original Array: ";
for (i = 0 ; i < size ; i++)
{
cout<<orig.arr1[i]<<" ";
}
cout<<endl;
cout<<"Ascending Array: ";
for (i = 0 ; i < size ; i++)
{
cout<<asc.arr1[i]<<" ";
}
cout<<endl;
cout<<"Descending Array: ";
for (i = 0 ; i < size ; i++)
{
cout<<desc.arr1[i]<<" ";
}
cout<<endl;
getch();
}
It compiles properly but it ('asc' and 'desc') displays numbers that are different from the 'orig' object.
The proper solution is something like this:
struct Foo
{
std::vector<int> arr;
friend std::ifstream & operator>>(/*...*/);
};
The implicitly defined assignment operator already does exactly what you need, and clever code reuse is the heart of C++ programming ("a language for library design").
If you want to write it by hand, you have to make the copy yourself:
struct Bar
{
unsigned int len;
int * arr;
Bar & operator=(Bar const & rhs)
{
len = rhs.len;
delete[] arr;
arr = new int[len];
for (unsigned int i = 0; i != len; ++i) { arr[i] = rhs.arr[i]; }
return *this;
}
Bar() : len(), arr() { }
// more constructors
Bar(Bar const &); // exercise: write this!
~Bar() { delete[] arr; }
};
This is a terrible, terrible idea, though, since this pattern doesn't generalize at all: it isn't exception safe -- imagine one of the copies in the for-loop threw an exception. Now you've lost your original data and leaked memory.
A better solution would be to allocate a temporary buffer first:
int * temp = new int[len];
for (...) temp[i] = rhs.arr[i];
delete[] arr;
arr = temp;
Now this code is quickly getting very ugly, and imagine you had more than one of those!
In a nutshell: use std::vector.
You don't need a temporary array object in the assignment operator, and you should copy to the array in this, and then return *this:
arr &operator=(const arr &eq)
{
// If "this" already has an array, then delete it
if (arr1)
delete [] arr1;
// Create a new array of the same length as the one we're assigning from
len = eq.len;
arr1 = new int [len];
// And copy the array
memcpy(arr1, eq.arr1, len * sizeof(int));
// Returning "*this" allows the assignment operator to be chained
return *this;
}
what you have implemented in operator overloading is quite confusing and seems wrong to me
arr& operator = (const arr& eq) //for copying two arrays. <--- my overloader
{
arr temp1(eq.len);
arr *pttemp;
int i=0;
//temp.arr1=new int[eq.len];
//temp.len = eq.len;
for(i = 0 ; i < eq.len ; i++)
{
temp1.arr1[i] = eq.arr1[i];
}
pttemp = &temp1;
return temp1;
};
1.why are you creating a new object temp?
2.why create a pointer of type arr. and assigning pttemp to point to temp whose scope is with in the function and then you are not using
it anywhere!!
you need not create a new object inside the function as "this" pointer is implicitly passed to the function.
you should overload it this way
arr& operator = (const arr& source)
{
//this->len = source.len;
len = source.len;
for(int i=0;i < source.len ; i++)
{
//this->arr1[i] = source.arr1[i];
arr1[i] = source.arr1[i];
}
return *this;
}
Your copy constructor also looks wrong, it doesn't copy the contents of the array.
I agree with Kerrek that you should use vector. But since you appear to be trying to re-implement vector for yourself, here's a simple "correct" way to manage the resources in your class, for illustration:
class arr
{
public:
// switch order of data members, we want to initialize "len" first
int len;
int *arr1;
// default constructor
// you could use "new int[len]()" instead, to zero-initialize the array
arr() : len(5), arr1(new int[len]) {}
// constructor with size
arr(int size) : len(size), arr1(new int[len]) {}
// copy constructor
arr(const arr &rhs) : len(rhs.len), arr1(new int[len]) {
std::copy(rhs.arr1, rhs.arr1 + len, arr1);
}
// destructor
~arr() {
delete[] arr1; // *not* "delete", you *must* use "delete[]"
}
// swap function (this is useful, observe that it cannot throw)
void swap(arr &rhs) {
std::swap(len, rhs.len);
std::swap(arr1, rhs.arr1);
}
// assignment operator
arr &operator=(arr temp) { // parameter by value uses the copy ctor
// so, anything that could throw (the allocation) is complete,
// before we make any modifications to this object.
// see how useful "swap" is, and the fact it cannot throw?
swap(temp);
return *this;
}
// for C++11
// move constructor
arr(arr &&rhs) : len(rhs.len), arr1(rhs.arr1) {
rhs.arr1 = 0;
}
};
Btw, the name of the data member arr1 makes me fear that you're going to add a second array later. Do not do this, it's far more trouble to write a class that correctly manages two resources, than it is to write a class that correctly manages one resource and another class that has two of those as data members.