Operator Overloading - c++

I'm new to C++, this is my first week since the upgrade from fortran. Sorry if this is a simple question, but could someone help me with operator overloading. I have written a program which has two classes. One object contains a vector and two scalars, the other class simply contains the first object. In a test implementation of this code I suspect the operator overloading to be at fault. The program tries to accomplish the following goals:
1) Initialize first structure.
2) Initialize a second structure containing the initialized first structure. After this is imported, the value val0 = 10 is added to every element of the vector in the enclosing structure, structure2.structure1 .
3) Output structure1 and structure2 variables to compare.
For this simple program my output is:
100
100
0
0
0 0 10
1 1 11
2 2 12
3 3 13
...
I was expecting:
100
100
0
10
0 0 10
1 1 11
2 2 12
3 3 13
...
Clearly my overloaded = operator is copying my vector properly, but one of the scalars? Could someone help?
#include <iostream>
using namespace std;
typedef double* doublevec;
// This first class contains a vector, a scalar N representing the size of the vector, and another scalar used for intializing the vector.
typedef class Structure1
{
int N, vec0;
doublevec vec;
public:
// Constructor and copy constructor.
Structure1(int Nin, int vecin) : N(Nin), vec0(vecin) { vec = new double [N]; for(int i = 0; i < N; i++) { vec[i] = i + vec0; } }
Structure1(const Structure1& structurein);
// Accessor functions:
int get_vec0() { return vec0; }
int get_N() { return N; }
doublevec get_vec() { return vec; }
// Overide equivalence operator:
Structure1& operator=(const Structure1& right)
{
//Handle Self-Assignment
if (this == &right) return *this;
N = right.N;
vec0 = right.vec0;
for (int i = 0; i < N; i++)
{
vec[i] = right.vec[i];
}
return *this;
}
// Destructor:
~Structure1() { delete []vec; }
} Structure1;
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for(int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
}
// This class just contains the first structure.
typedef class Structure2
{
Structure1 structure;
// Mutator Function:
void mutate_structure();
public:
// Constructor:
Structure2(const Structure1& structurein) : structure(structurein) { mutate_structure(); }
// Accessor Function:
Structure1 get_structure() { return structure; }
// Destructor:
~Structure2() {}
} Structure2;
void Structure2::mutate_structure()
{
int N = structure.get_N();
Structure1 tempstruct(N,10);
structure = tempstruct;
}
int main (int argc, char * const argv[])
{
const int N = 100;
Structure1 structure1(N,0);
Structure2 structure2(structure1);
cout << structure1.get_N() << endl;
cout << structure2.get_structure().get_N() << endl;
cout << structure1.get_vec0() << endl;
cout << structure2.get_structure().get_vec0() << endl;
for(int i = 0; i < N; i++)
{
cout << i << " " << structure1.get_vec()[i] << " " << structure2.get_structure().get_vec()[i] << endl;
}
return 0;
}

it looks like vec0 isn't initialized by your copy constructor...
Try modifying your copy constructor to:
Structure1::Structure1(const Structure1& structurein)
{
N = structurein.N;
vec = new double[N];
for (int i = 0; i < N; i++)
{
vec[i] = structurein.vec[i];
}
// ADD THIS LINE
vec0 = structurein.vec0;
}

Your copy-constructor Structure1::Structure1(const Structure1 &) doesn't copy vec0. It's not getting initialised at all, so gets whatever is in memory.
Also, you might want to check Structure1's operator=. If you assign a large vector to a small vector, then you'll potentially overflow the array in the destination. You might need to reallocate memory in operator=.

Related

C++: what if we don't allocate an object with new, but the class itself contains a new in constructor?

Hope my question isn't confusing. I'll explain that with code.
I'm learning constructor/desctructor and new/delete in C++. While comparing two piece of code, I'm thinking about where the object and it's members are allocated.
I got a little bit confused when I see the new in constructor and main, and delete in destructor and main:
In the first example, I think local object c is allocated in stack. And that means, members list pointer, two int values (size and capacity) are all in stack. The object also contains an array in size 10, however the array itself is allocated in heap since new is used. When the program ends, the local object c (including the pointer) will be freed automatically. And the array pointed by pointer list will be freed as well, by destructor. Is that correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector c(10);
for (int i = 0 ; i < 15 ; i++){
cout << c.append(i) << endl;
}
}
Now compared with the second example, object is created with new. So all members including pointer and two int values are all allocated from heap. The array itself is also in heap for the same reason as the first example. Before the program ends, there is a delete so the pointer and two int values are all freed. The array is also freed since the desctructor is called when delete command is issued. Is my understanding correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector *c;
c = new Collector(10);
for (int i = 0 ; i < 15 ; i++){
cout << c->append(i) << endl;
}
delete c;
cout << "Exiting program" << endl;
}

how to copy Int array to int pointer using constructor in C++

I am trying to insert int array x to int *v. here is my code . please provide me with optimal solutions and the reason behind it.
there is an error in this line. Instead of copying array value its taking garbage value. line v1=x;
class vector
{
int *v;
int size;
public:
vector(int m)
{
v = new int[size = m];
for (int i = 0; i < size; i++)
v[i] = 0;
}
vector(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
}
int operator *(vector &y)
{
int sum = 0;
for (int i = 0; i < size; i++)
sum += v[i] * y.v[i];
return sum;
}
void disp()
{
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << "\n";
}
};
int main()
{
clrscr();
int x[3] = { 1,2,3 };
int y[3] = { 4,5,6 };
vector v1(3);
//v1.disp();
vector v2(3);
v2.disp();
v1 = x;
v1.disp();
//v2=y;
v2.disp();
int r = v1 * v2;
cout << "R = " << r;
getch();
return 0;
}
You forgot to add the assignment operator in your vector class:
vector & operator=(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
return *this;
}
In the the line
v1=x;
May be, you are expecting it to invoke the second constructor which takes int* as argument. But it won't happen.
It can be seen as Type Conversion from Basic type to Class type. where we expect appropriate constructor will get invoked.
see http://www.hexainclude.com/basic-to-class-type-conversion/
But remember, Constructor will be invoked only once after the creation of object.
Here, in the line
vector v1(3);
the first constructor was already invoked. Then the line
v1=x;
won't invoke the second constructor now.
For every class, = operator is default overloaded . That is the reason why we can easily assign objects to one another.
Therefore, the line v1=x invokes default overloaded assignment = operator.
Here, it treats address of array x i.e., &x[0] as address of class object. As it is not address of vector class object
=> it results a Segmentation fault.
YOUR ANSWER
To assign int array to int pointer i.e., to the member variable int* v of the vector class,
overload assignment operator = inside the class .
or
Initialize the class object to array in first line itself. i.e.,
vector v1=x; // modify the class constructor to have size as a constant.

A heap has been corrupted when trying to run code

When ever I run my program it breaks and has the error "A heap has been corrupted" when debugging the program, it actually will go through the whole thing just fine and break on the system("PAUSE") which seems like an odd place to have an error. I am clueless where the issue is. The program worked just fine, until I added the operator overload for + and OS
Below is my code:
MAIN.CPP
#include "stdafx.h"
#include "vector.h"
// the printV function
// used to test the copy constructor
// parameter: a MyVector object
void printV(Vector);
int main()
{
cout << "\nCreating a vector Sam of size 4.";
Vector 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.";
Vector 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);
system("PAUSE");
return 0;
}
void printV(Vector v)
{
cout << "\n--------------------\n";
cout << "Printing a copy of a vector\n";
cout << v;
}
VECTOR.H
#pragma once
#include <iostream>
#include "stdafx.h"
using namespace std;
class Vector
{
private:
int vectorSize;
int vectorCapacity;
int *vectorArray;
public:
//A default constructor that creates an vector with a default capacity of 2
Vector();
//A parameterized constructor that creates a vector of capacity n
Vector(int n);
// A function, size(), that returns the size of your vector.
int size();
// A function, capacity(), that returns the capacity of the vector.
int capacity();
// A function, clear(), that deletes all of the elements from the vector and resets its size to zero and its capacity to two.
void clear();
// A function push_back(int n) that adds the integer value n to the end of the vector.If the vector is not large enough to hold this additional value, you must make the vector grow.Your grow algorithm should double the current capacity of the vector.Don't forget to consider the case where the initial capacity of the vector is zero.
void push_back(int n);
// A function at(int n) that returns the value of the element at position n in the vector.If the index n is greater than the size() of the vector, this function should throw an exception.
int at(int n);
friend ostream& operator<<(ostream& os, Vector vt);
Vector operator=(Vector&);
VECTOR.CPP
#include "stdafx.h"
#include "vector.h"
Vector::Vector()
{
vectorSize = 0;
vectorCapacity = 0;
vectorArray = 0;
}
// Create new array with given capacity
Vector::Vector(int n)
{
vectorCapacity = n;
vectorArray = new int[vectorCapacity];
}
//Return array size
int Vector::size()
{
return vectorSize;
}
// Return array capacity
int Vector::capacity()
{
return vectorCapacity;
}
// clear array values
void Vector::clear()
{
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = 0;
vectorCapacity = 2;
}
// Add number to array and double array size if needed
void Vector::push_back(int n)
{
int test = 100;
if (vectorCapacity > vectorSize)
{
vectorArray[vectorSize] = n;
vectorSize++;
}
else {
if (vectorCapacity == 0) {
vectorArray = new int[4];
vectorArray[0] = n;
vectorCapacity = 4;
vectorSize++;
}
else {
int newCapacity = vectorCapacity * 2;
// Dynamically allocate a new array of integers what is somewhat larger than the existing array.An algorithm that is often used is to double the size of the array.
int *tempArray = new int[newCapacity];
// Change capacity to be the capacity of the new array.
vectorCapacity = newCapacity;
// Copy all of the numbers from the first array into the second, in sequence.
for (int i = 0; i < Vector::size(); i++)
{
tempArray[i] = vectorArray[i];
}
delete[] vectorArray;
vectorArray = new int[newCapacity];
for (int i = 0; i < Vector::size(); i++)
{
vectorArray[i] = tempArray[i];
}
delete[] tempArray;
// Add the new element at the next open slot in the new array.
vectorArray[vectorSize] = n;
// Increment the size;
vectorSize++;
}
}
}
// Return Value and given point in array
int Vector::at(int n)
{
return vectorArray[n];
}
// Cout Vector
ostream& operator<<(ostream& os, Vector vt)
{
int size = vt.size();
for (int i = 0; i < size; i++) {
os << "index " << i << " is " << vt.at(i) << endl;
}
return os;
}
// Set one vector to equil another
Vector Vector::operator=(Vector& right) {
// Clear array on left
for (int i = 0; i < sizeof(vectorArray); i++)
{
vectorArray[i] = '\0';
}
vectorSize = right.size();
vectorCapacity = right.size() * 2;
// Assign values from left to right
for (int i = 0; i < vectorSize; i++)
{
vectorArray[i] = right.at(i);
}
return vectorArray[0];
}
The problem is operator=()
Why ?
You start with sam having a capacity of 4. You push back 12 items in it. When you reach the 5th element, the capacity is doubled from 4 to 8. Then you then reach the 9th element, the capacity is increased to 24.
You then have joe with an initial capacity of 4. You push back 6 items in it. When you reach the 5th element, its capacity is increased to 8.
When you then do joe = sam, your operator overwrites joe's size and capacity but without verifying that the capacity matches, and without allocating missing capacity. As you then try to copy 12 elements in a vector having in reality only a capacity of 8, you do some collateral damage in memory and corrupt the heap.
Solution
Do not overwrite blindly the capacity. Keep the capacity if it's sufficient. If not, align the capacity and reallocate.
// Set one vector to equal another
Vector Vector::operator=(Vector& right) {
//...
if (vectorCapacity < right.vectorCapacity) {
delete[] vectorArray; // assuming pointer is either nullptr or valid array
vectorArray = new int[right.vectorCapacity];
vectorCapacity = right.vectorCapacity;
}
vectorSize = right.size();
// Assign values from left to right
//...
return *this;
}
Note that it would be better to return the vector by reference !
There are lots of errors, but the one that causes the described symptoms is the operator= never allocates a new array of int for vectorArray
Each use of sizeof(vectorArray) is also wrong. That is just the size of a pointer, not the allocation of the area pointed to.
Each place that does vectorArray[i] = '\0'; is at best pointless, and whatever was intended, that is the wrong way to do it. Enough so I can't even guess the intent.
In the clear function the only necessary step was vectorSize = 0; The rest was at best pointless. Setting capacity to 2 there is bizarre, though it does no major harm.
operator= ought to have return type Vector& and not Vector and should return *this not construct a Vector whose capacity is a value from the old one. In general, almost any operator= member of a class should return *this. Exceptions to that rule are way beyond the level where you are currently trying to learn.
Given all of the answers so far, the other issue is that you failed to implement a user-defined copy constructor:
Vector(const Vector& n);
This function has to be implemented correctly since you have functions returning Vector by value. Since you didn't implement it, copying will not work correctly.
Second issue is that you should be returning the Vector by reference, not by value in the operator= function.
My first suggestion is to take whatever code you have now in your operator= and do the work of the "real" copying in the copy constructor. Here is a streamlined version of what the copy constructor should look like:
#include <algorithm>
//..
Vector::Vector(const Vector& rhs) : vectorCapacity(rhs.vectorCapacity),
vectorArray(new int[rhs.vectorCapacity]),
vectorSize(rhs.size())
{
std::copy(rhs.vectorArray, rhs.vectorArray + rhs.vectorCapacity, vectorArray);
}
Note the usage of the member initialization list, and the call to the function std::copy (you could also have written a loop, but just to show you that there are functions that do the copy without hand-written loops).
The second thing is that your destructor should simply do this:
Vector::~Vector()
{ delete [] vectorArray; }
Then operator= becomes very simple using copy / swap.
#include <algorithm>
//...
Vector& operator=(const Vector& v)
{
Vector temp = v;
swap(this.vectorCapacity, temp.vectorCapacity);
swap(this.vectorArray, temp.vectorArray);
swap(this.vectorSize, temp.vectorSize);
return *this;
}
This works only if the copy constructor and destructor work correctly, since operator= takes advantage of these functions.
Read more about the Rule of 3 and the copy / swap idiom.

Operator Overloading and array handling in C++

I am writing a Little Man computer simulation and i want to overload the Indexing operator []. I have create a class called LMC and have done the following:
#include <iostream>
using namespace std;
class LMC
{
public:
LMC();
void display();
int& operator[](int index);
~LMC();
private:
int **array;
};
LMC::LMC()
{
array = new int*[100];
for(int i = 0; i < 100; i++)
{
array[i] = new int[3];
}
return array;
}
void LMC::display()
{
for(int i = 0; i < 100;i++)
{
for(int j = 0; j <3;j++)
{
array[i][j] = 0;
array[i][2] = i;
cout << array[i][j]<<" ";
}
cout << endl;
}
}
int& LMC::operator[](int index)
{
return array[index][2];
}
LMC::~LMC()
{
for(int i =0; i < 100 ; i++)
{
delete [] array[i];
}
delete [] array;
array = NULL;
}
int main()
{
LMC littleman;
while(true)
{
int mailbox;
int function;
cout << "What is Mailbox number?" << endl;
cin >> Mailbox;
cout << "What is the function you want to use?" <<endl;
cin >> finction;
//the function is numbers eg 444 and 698;
littleman.display();
littleman[Mailbox] = function;
}
return 0;
}
I can run the program with no error. When i state that mailbox = 0 and function = 123 the is no problem.
This is displayed:
0 0 0
1 0 0
2 0 0
3 0 0
//continuing to 99
This display is wrong. The following must be displayed:
0 0 123
1 0 0
2 0 0
//continuing to 99
Do i have a logical error or am i overriding the array to display the original and how can i fix it?
Your code has a number of errors which will not let it compile namely:
in the LMC() constructor, you have return array;. Constructors never return anything (they don't even have the return type), so you can not use return in them.
after void LMC::display(), you have a ;, which is an error, because this is not a definition, but implementation. You should omit it and just leave void LMC::display() { <...> }
void LMC::display() is missing the closing } in the end, right before the operator[].
in main() you have typos in Mailbox (capital M in one case, and normal m in another. In C+++ Mailbox and mailbox are different variables) and finction instead of function.
As for your problem, you are rewriting the values of the aray in display() function:
array[i][j] = 0;
array[i][2] = i;
That's why you don't see any results.
These lines
array[i][j] = 0;
array[i][2] = i;
in LMC::display() destroy the contents of the array you're trying to display.
Furthermore, there's an extra semicolon at the end of void LMC::display();, so your code is not supposed to compile.

operator overloading in c++ - A query

I was reading a book on operator overloading in c++ and I encountered the following code:
class Array {
...
public:
Array & operator << ( int x) {
// insert x at the end of the array
}
};
Next It says: that overloading of the form a << x << y << z ;
wll not workSo It suggests that second invocation is treated as :( (a << x)<< y ) << z .so it recommends using return *this;
But I am not getting how return *this functions here? Please help!Here is the entire code:
#include <iostream>
#include <cstdlib>
using namespace std;
class Array {
int *a;
int capacity;
int size;
int incr;
public:
Array (int c=10) {
a = new int[c];
capacity = c;
for (int i=0; i<c; i++) a[i]=0;
size=0;
incr = c;
}
Array &operator << (int x) {
if(size<capacity) a[size++] = x;
else {
int *tmp = new int [capacity+incr];
for (int i=0; i<size; i++) tmp[i]=a[i];
delete[] a;
a = tmp;
a[size++]=x;
capacity = capacity+incr;
}
return *this;
};
int operator [] (int i) {
if(i<size) return a[i];
};
};
int main (int argc, char *argv[]) {
int s = atoi (argv[1]);
Array A (s);
for (int i=0; i<s; i++) A << i << i+1;
for (int i=0; i<s; i++) cout << A[i] << endl;
}
This really has nothing to do with operator overloading. It's called chaining and it's easier to explain using regular member functions. Suppose you defined a member function called insert like this:
Array& insert(int x) {
// insert x at the end of the array
return *this;
}
The return *this will return a reference to the current object so that you can chain calls like this:
Array a;
a.insert(0).insert(1).insert(2);
Which is essentially equivalent to:
Array a;
a.insert(0);
a.insert(1);
a.insert(2);
Each call to insert() will return a reference to the original object, allowing other calls to be made using that returned reference. You can overload the << operator to do the same thing:
Array& operator<<(int x) {
// insert x at the end of the array
return *this;
}
Now you can chain calls like this:
Array a;
a << 0 << 1 << 2;
You may be getting confused because of the spacing of Array &operator <<. The return value of the function is Array&, a reference to the array object.
Here's an example. In your call A << i << i+1, the A << i is called first and a reference to the updated A is returned. Next A << i+1 is called, with that new reference.
Yes everything is ok with your code. operator << in your semantics will and returning refference to same object which called it. You can see same in code of operator << of std::ostream and operator >> of std::istream.