C++ Scope Resolution Issue - c++

Yesterday my class had a laboratory exam where-in we had to make a matrix class and overload the operation+(). I thought that I had it correct until I went to go do my unit testing... I know this is a lot of text; however, I spent the remainder of the lab trying to figure out what was going wrong and could NOT figure out why the Temporary Object Matrix was going out of scope prior to the assignment operator call.
Code as follows:
Matrix Header
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix
{
Public:
// Constructor and Destructor Suite
Matrix(int x, int y); // Lab TA stated that Matricies would never go above two dimensions
~Matrix();
// Access and Mutation
void set(int row, int column, int value); // This function sets the value of a given matrix coordinate at row, column to value
int get(int row, int column) const; // This function returns the value of a matrix at row, column
Matrix& operator=(const Matrix& Q)
{
cout << "Called Assignment" << endl;
int r, c;
r = Q.rows; c = Q.columns;
for (int i = 0; i < r; i++)
{
for (int k = 0; k < c; k++)
{
cout << "Address of Calling Objet pointer Int: " << this->pMatrixOfInt[i][k] << setw(5) << *this->pMatrixOfInt[i][k] << endl;
cout << "Address of Reference Object: " << Q.pMatrixOfInt[i][k] << setw(5) << *Q.pMatrixOfInt[i][k] << endl;
*(this->pMatrixOfInt[i][k]) = *(Q.pMatrixOfInt[i][k]);
}
}
return *this;
}
const Matrix operator+(const Matrix& Q);
friend ostream& operator<<(ostream& output, const Matrix& Q);
friend istream& operator>>(istream& input, Matrix& Q);
private:
int rows, columns;
int* pMatrixOfInt[50][50]; // Specification document said that these values would never go above 50
};
Matrix.cpp
/*
Matrix Class Definition
14 March 2014
*/
#include <iomanip>
#include <iostream>
#include "Matrix.h"
// Constructor
Matrix::Matrix(int x, int y)
{
cout << "Constructor Called" << endl;
this->rows=x;
this->columns=y;
for (int i=rows-1; i>=0; i--) // If X and Y are both 50 then the starting value
{ // for i and k should be 49 because of how arrays
for (int k=columns-1; k>=0; k--) // are indexed. Hence the rows-1
{
pMatrixOfInt[i][k] = new int;
}
}
}
// Destructor
Matrix::~Matrix()
{
cout << "Destructor Called" << endl;
for (int i=rows-1; i>=0; i--) // If X and Y are both 50 then the starting value
{ // for i and k should be 49 because of how arrays
for (int k=columns-1; k>=0; k--) // are indexed. Hence the rows-1
{
delete pMatrixOfInt[i][k];
}
}
}
// Access and Mutation
void Matrix::set(int row, int column, int value)
{
*pMatrixOfInt[row][column] = value;
}
int Matrix::get(int row, int column) const
{
return *pMatrixOfInt[row][column];
}
// Overloaded Addition Operator (Possible Scope Problem)
const Matrix Matrix::operator+(const Matrix& Q)
{
cout << "Addition Operator Called" << endl;
int rows, columns;
rows = Q.rows;
columns = Q.columns;
Matrix newMatrix(rows, columns);
cout << "newMatrix Rows: " << newMatrix.rows << " -- newMatrix columns: " << newMatrix.columns << endl; // Make a new matrix. Constructor will initialize the pointer Matrix
int newValue;
for (int i=0; i<rows; i++)
{
for (int k=0; k<columns; k++)
{
newValue = this->get(i,k);
newValue += Q.get(i,k);
newMatrix.set(i,k, newValue);
cout << setw(5) << newMatrix.get(i, k);
}
cout << "\n";
}
return newMatrix;
}
// Friend definitions for i/ostreams.
ostream&::operator<<(ostream& output, const Matrix& Q)
{
for (int r = 0; r<Q.rows; r++)
{
for (int c = 0; c<Q.columns; c++) // hahaha
{
output << setw(4) << Q.get(r,c);
}
output << "\n";
}
return output;
}
istream&::operator>>(istream& input, Matrix& Q)
{
int value;
for (int r = 0; r<Q.rows; r++)
{
for (int c = 0; c<Q.columns; c++)
{
input >> value;
Q.set(r,c,value);
}
}
return input;
}
When I tried to do something like this:
newMatrix = oldMatrixA + oldMatrixB;
cout << newMatrix;
I received the following series of outputs and then a BLOCK_HEADER_ERROR:
Addition Operator Called
0 1 2 3
1 3 5 7
Destructor Called
Assignment Called
Lots of output here regarding address of calling object and value along with the reference object and value of that too
!!!BLOCK_HEADER_ERROR!!!
Can anyone tell me why the Temporary Object returned by the addition operator is going out of scope prior to the assignment operator even though they are on the same line and newMatrix is a return object and thus should not be destroyed until the scope calling it calls for its destruction?
Thank you in advance for your help, I didn't sleep well last night because the TA made me turn in work that I knew was bugged and I haven't been able to figure out the problem.
I know that it's a lot of code and this is the longest question I've posted to StackOverflow ever; however, I like sleeping well and I don't think I'll rest soundly until I know what's going wrong.

Why do you use pointers to store the values? Use plain integers instead and you are fine.
At first think about the "too early" destruction:
In your code you actually have two temporaries (if no return value optimization takes place):
The first one is newValue and the second one your rvalue temporary that gets returned by operator+.
After a copy of newValue to the temporary rvalue has been made newValue is destructed (the message you see).
Second problem is: You did not specify a custom copy constructor (think about the rule of three). Hence the rvalue temporary copy has all the pointers to the integers that you freed when destructing newValue.
If you can't use plain integers, then you have to write your own copy constructor that really copies (allocates new integers for the new matrix).
If you can use plain integers, then use them and everything is fine (no need for custom destructor/copy constructor/copy assignment operator)
An example copy constructor:
Matrix::Matrix(const Matrix &other) {
this->rows=other.rows;
this->columns=other.columns;
for (int row = 0; row < rows; ++row) {
for (int column = 0; column < columns; ++column) {
// allocate a new integer with the value
// copied from the other matrix
pMatrixOfInt[row][column] = new int(*other.pMatrixOfInt[row][column]);
}
}
}

Related

c++ empty copy assignment operator copies data

I am sort of new to c++ and wanted to write a small matrix library which has a base class Matrix from which some new matrix types like SparseMatrix, DenseMatrix, HashMatrix etc.
My base class looks like this:
class Matrix {
protected:
int m,n;
public:
Matrix(int m_p, int n_p) : m(m_p), n(n_p){
std::cout << "gen constr" << std::endl;
}
Matrix(Matrix& other) = delete;
Matrix() = delete;
virtual ~Matrix() {}
int getM() const {
return m;
}
int getN() const {
return n;
}
virtual double& get(int m, int n) = 0;
virtual double get(int m, int n) const = 0;
inline double& operator() (int m, int n){
return get(m,n);
}
inline double operator() (int m, int n) const{
return get(m,n);
}
friend std::ostream &operator<<(std::ostream &os, Matrix &matrix) {
using std::scientific;
using std::fixed;
os << std::fixed << std::setprecision(2) << scientific << std::setfill(' ');
for(int i = 1; i <= matrix.getM(); i++){
for(int j = 1; j <= matrix.getN(); j++){
os << std::setw(10) << matrix.get(i,j) << " ";
}
os << "\n";
}
return os;
}
Matrix& operator=(const Matrix& other) {
// std::cout << "equality assign" << std::endl;
return *this;
}
};
As you can see, I have overwritten the equality assign operator which simply returns the object and does not actually copy values.
My first implementation of DenseMatrix is very straight forward:
class DenseMatrix : public Matrix{
private:
double* data;
public:
DenseMatrix(int mP, int nP) : Matrix(mP, nP){
std::cout << "gen constr base" << std::endl;
this->data = new double[mP * nP]{0};
}
DenseMatrix() = delete;
~DenseMatrix() {
delete this->data ;
}
double &get(int m, int n) {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
double get(int m, int n)const {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
};
Furthermore the main() function looks like this:
DenseMatrix mat(3,3);
for(int i = 1; i<= 3; i++){
mat(i,i) = i;
}
DenseMatrix mat2(3,3);
mat2 = mat;
std::cout << mat << std::endl;
std::cout << mat2 << std::endl;
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
As you can see, I create two matrices first. I adjust the values for the first matrix and leave the values of the second matrix default to 0. Yet after calling the equality assign operator, the content of the second matrix changes even tho the function I implemented has basically no code which affects the matrix.
I do not understand this behavior and would be very happy if someone could briefly explain what is going on here.
Thank you very much for your patience and help :)
You have not deleted or defined the operator= copy-assignment operator for DenseMatrix, so the compiler will synthesize one for you. This function is going to do a member wise copy of the data members, in this case double *data. Since the pointer is going to point to the same contents in both mat and mat2, you see the same contents when you print them out.
Note that this is probably not what you want. One issue is that your DenseMatrix destructor is going to delete data twice, leading to possibly a segfault.
You didn't define assignment operator for DenseMatrix.
The implicitly generated assignment operator assigns the sub objects. The base sub object will be assigned using the overloaded assignment operator of Matrix and therefore the dimensions stored within the base are not modified - but you had specified the dimensions to be the same, so they would have been assigned with the same values anyway.

Pass Object by Reference error in C++

I have a MatrixTypeheader file which has the following definition :
http://pastebin.com/DMzf1wGB
//Add Two Matrices and store result into another matrix
void Add(MatrixType otherMatrix, MatrixType& resultMatrix);
The implementation of the method above is as such :
void MatrixType::Add(MatrixType otherMatrix, MatrixType& resultMatrix)
{
cout << "Inside Add func!" << endl;
cout << "other matrix : " << endl;
otherMatrix.PrintMatrix();
for (int i = 0; i < numRows; i++) {
for (int j = 0; j < numCols; j++) {
resultMatrix.values[i][j] = values[i][j] + otherMatrix.values[i][j];
}
cout << "\n";
resultMatrix.PrintMatrix();
cout << "\n";
}
}
Definition of PrintMatrix() :
void MatrixType::PrintMatrix()
{
//Pre: None
//Post: Matrix is printed row wise
for (int i = 0; i < numRows; i++) {
cout << "[ ";
for (int j = 0; j < numCols; j++) {
cout << values[i][j];
}
cout << "]";
cout << "\n";
}
}
Now in my Main.cpp I have MatrixType array like this : MatrixType matrixStore[10] to store 10 MatrixType objects. The complete code for Main.cpp is here : http://pastebin.com/aj2eEGVS
int rows = matrixStore[index1].getRowSize();
int cols = matrixStore[index1].getColSize();
cout << "The two matrices can be added!" << endl;
cout << "Computing... " << endl;
//Create Result Matrix and a pointer variable to it
MatrixType pResultMatrix = MatrixType(rows, cols);
matrixStore[resultIndex] = pResultMatrix;
//Invoke Add function
matrixStore[index1].Add(matrixStore[index2], matrixStore[resultIndex]);
Now when in my Add() function I do otherMatrix.PrintMatrix() it prints out the values of the matrix invoking the Add() function. And due to this => either I do not have reference to the matrix object invoking the method or the matrix object being passed as the parameter!
Also whenever I do PrintMatrix() after I have added values (in the next round of Switch Case), I always get junk values.
Any solution/explanation to this ?
TIA
The main problem is not in this part of your code but during the matrix creation/initialization. You are storing objects in the array which can be good (especially I like it because it is created on the stack which is much faster, just be aware to do not create too long array to avoid stack overflow) but you have to consider this overall of your code.
For example in the Main.cpp line 38 you copy the content of matrixobject into the array but after that you modify the matrix object which is different from the object which is in the array! This means that the content of the matrix object in the array has some random values. You should modify directly the object in the array, it does not make any sense to have that temporary one.
For example:
matrixStore[index] = MatrixType(rows, cols);
for (int i = 0; i < rows; i++)
{
std::cout << "Row " << i << " : ";
for (int j = 0; j < cols; j++)
{
std::cin >> value;
matrixStore[index].StoreItem(value, i, j);
}
}
I think after this change the part what you copied here should work because there you are working in the array directly.
Some small suggestions:
Pass MatrixType object always as reference if possible. For example, in Add function also the òtherMatrix can be a const ref, your code will be much efficient because the object copy will be not involved. For example:
void MatrixType::Add(const MatrixType& otherMatrix, MatrixType& resultMatrix);
Here the otherMatrix is an input, the resultMatrix is (can be) an output parameter.
In C++ there is real bool type. Avoid bool isAddComp ... if (isAddComp != 0)code, just use if (isAddComp), this is the C++ way.
I would start to use std::vector instead of common arrays, much more flexible and very useful to learn how can you use it.
Personally I would not use ùsing namespace for std it is short and better to read your code (but maybe this is just my code style).
Looking at the code here: http://pastebin.com/aj2eEGVS
It looks like the only reason you're creating a local matrix in all your paths, for example:
MatrixType matrix = MatrixType(rows, cols);
is to assign values to the members numRows and numCols. I see you have a commented out SetSize method. I would assume you don't want to do use it because you think the rows and columns shouldn't change after creation.
In that case, your matrixStore should be created as pointers:
MatrixType* matrixStore[10];
Now instead of doing:
MatrixType matrix = MatrixType(rows, cols);
matrixStore[index] = matrix;
You do this:
matrixStore[index] = new MatrixType(rows, cols);
And just use:
matrixStore[index]->StoreItem(value, i, j);
or whatever you want to do with it.
In the end, you just call:
delete matrixStore[index];
For all matrices you have used "new" on. The best way to do this is to assign them to nullptr in the beginning.
MatrixType* matrixStore[10];
for ( unsigned int i = 0; i < 10; ++i )
{
matrixStore[i] = nullptr;
}
And in the end:
for ( unsigned int i = 0; i < 10; ++i )
{
if (nullptr != matrixStore[i])
{
delete matrixStore[i];
}
}
In short, matrixStore stores object values, not pointers (as you expect).
//Create Result Matrix and a pointer variable to it
MatrixType pResultMatrix = MatrixType(rows, cols);
matrixStore[resultIndex] = pResultMatrix;
Seems you expect to store pointer variable, but it's not true. MatrixType value is stored in matrixStore.
The result of this is incorrect matrixStore filling (code from your link):
MatrixType matrix = MatrixType(rows, cols);
matrixStore[index] = matrix;
cout << "Address of matrixStore[index] : " << &matrixStore[index] << endl;
cout << "Address of new matrix is : " << &matrix << endl;
int value;
for (int i = 0; i < rows; i++) {
cout << "Row " << i << " : ";
for (int j = 0; j < cols; j++) {
cin >> value;
matrix.StoreItem(value, i, j);
}
}
All changes to matrix are lost as matrixStore contains old copy of matrix object.
Solution:
The proper declaration of matrixStore to keep pointers is:
MatrixType* matrixStore[10]
In case you would like to operate with MatrixType value objects you need to copy objects into matrixStore all time you've modified them.
Looking at the code in http://pastebin.com/aj2eEGVS
It seems to me you are not initializing the matrix in matrixStore. You are filling the local variable matrix.
MatrixType matrix = MatrixType(rows, cols); // LOCAL VARIABLE
**matrixStore[index] = matrix;** // you are copying the uninitialized matrix
// ...
int value;
for (int i = 0; i < rows; i++) {
cout << "Row " << i << " : ";
for (int j = 0; j < cols; j++) {
cin >> value;
matrix.StoreItem(value, i, j); // LOCAL VARIABLE
}
}
cout << endl;
//Print matrix so the use can see
matrix.PrintMatrix(); // PRINT LOCAL VARIABLE

Matrix Class Error: Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

this is my first time of using stackoverflow, nice to meet you all.
I am writing a matrix class that overloads assignments,addition, subtraction...etc.
The assignment operator "=" overloading part seems to work fine, but if I attempt to overload the addition "+" operator, I get error message like this:
"Debug Assertion Failed!
Program:...nts\C++\week6....\week6matrix.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgdel.cpp
Line:52
Expression:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)"
But if I remove "delete[]matrix" in my destructor, everything seems to work, but due to the requirement of this project, I needed to have this term in my destructor.
I would have posted a picture but its my first time of using this website, so I don't have the reputation to do that yet so I apologise if my question doesn't seem to make sense, but I ll try my best to explain it if you have any further questions regarding my question.
Thank you.
#include<iostream>
#include <stdlib.h>
using namespace std;
//dynamic matrix
class dymatrix
{
friend ostream & operator << (ostream &os, dymatrix &om);
friend istream & operator >> (istream &is, dymatrix &om);
private:
int rows;
int columns;
double *matrix;
public:
dymatrix(){cout<<"Default constructor called"<<endl; columns = 0; rows=0; matrix=0;}
dymatrix(int inrows, int incolumns)
{
rows = inrows;
columns = incolumns;
matrix = new double [inrows*incolumns];
for (int i=0; i<inrows*incolumns; i++)
{
matrix[i]=0;
}
}
int lengthr() const {return rows;} //Returns number of rows.
int lengthc() const {return columns;} //Return number of columns.
dymatrix& operator=(dymatrix&);
~dymatrix(){cout<<"Destructor called"<<endl;delete[] matrix;}
int index(int i, int j) //This member function returns the position of each index.
{
if (j > 0 && j <=rows && i > 0 && i <=columns)
{
return (i-1)+(j-1)*columns;
}
else {cout<<"Error, out of range"<<endl; exit (1);}
}
double & operator()(int i, int j) {return matrix[index(i,j)];} //The operator () returns the position of j and i in 1D array.
dymatrix operator + (dymatrix &arr) //overloading addition.
{
if (rows !=arr.rows && columns != arr.columns)
{
cerr<<"SIZE DO NOT MATCH, YOU FAIL"<<endl; exit(1);
}
dymatrix new_matrix(rows,columns);
for (int j = 0; j < arr.rows*arr.columns; j++)
{
//for (int i = 1; i <= arr.columns; i++)
//{
//cout<<"****"<<j<<endl;
new_matrix.matrix[j]= matrix[j]+arr.matrix[j]; //Putting in the data into this dynamic array for each element.
//}
}
return new_matrix;
}
}; //Class end.
dymatrix & dymatrix::operator = (dymatrix &arr) //Overloading "=" operator.
{
if (&arr == this) return *this; //If the array is the same, no need to change, just to print. The key word "this" is a pointer to the object, and *this gives the object.
delete[] matrix; matrix =0; rows =0; columns =0;
rows = arr.rows; //Setting row length.
columns = arr.columns; //Setting column length.
if(rows*columns > 0)
{
matrix = new double [rows*columns]; //Defining a dynamic array here.
for (int j = 1; j <= rows; j++) //Assigning each term to each term.
{
for (int i =1; i <=columns;i++ )
{
matrix[index(i,j)] = arr(i,j); //This is the assigning part, the loop above loops everything so that each term is assigned.
}
}
}
return *this; //Return
}
istream & operator >> (istream &is, dymatrix &om) //Overloading ">>" operator here to
{
cout<<"Please enter the number of rows you want"<<endl;
is >> om.rows; //Inputting number of rows.
cout<<"Enter the number of columns you want"<<endl;
is >> om.columns; //Inputting number of columns.
cout<<"Enter matrix"<<endl;
om.matrix = new double [om.rows*om.columns]; //Making a dynamic array here to put the data in.
for (int j = 1; j <= om.rows; j++)
{
for (int i = 1; i <= om.columns; i++)
{
is >> om.matrix[om.index(i,j)]; //Putting in the data into this dynamic array for each element.
}
}
return is;
}
ostream & operator << (ostream &os, dymatrix &om) //To output the matrix in an standard matrix way
{
for(int j= 1; j<=om.rows; j++)
{
os<<endl<<endl;
for (int i = 1; i <=om.columns;i++)
{
os << om.matrix[om.index(i,j)]<<"\t"; //Similar method used in istream.
}
}
return os;
}
int main()
{
dymatrix a1;
cin >> a1; //Define the rows of the matrix
cout << a1<<endl<<endl;
dymatrix a2;
cin >> a2;
cout << a2<<endl<<endl;
dymatrix resu_a1;
resu_a1=a1+a2;
cout<<"Addition = "<<resu_a1<<endl;
dymatrix resu_a3;
resu_a3 = a1;
cout<<"Assigning = "<<resu_a3<<endl;
return 0;
}
This is my destructor:
~dymatrix(){cout<<"Destructor called"<<endl;delete[] matrix;}
This is when I overload the assignment "=" operator(outside the class) which seems to work:
dymatrix & dymatrix::operator = (dymatrix &arr) //Overloading "=" operator.
{
if (&arr == this) return *this; //If the array is the same, no need to change, just to print. The key word "this" is a pointer to the object, and *this gives the object.
delete[] matrix; matrix =0; rows =0; columns =0;
rows = arr.rows; //Setting row length.
columns = arr.columns; //Setting column length.
if(rows*columns > 0)
{
matrix = new double [rows*columns]; //Defining a dynamic array here.
for (int j = 1; j <= rows; j++) //Assigning each term to each term.
{
for (int i =1; i <=columns;i++ )
{
matrix[index(i,j)] = arr(i,j); //This is the assigning part, the loop above loops everything so that each term is assigned.
}
}
}
return *this; //Return
}
But when I overload the addition operator "+" inside the class, I get the error which I quoted above.
dymatrix operator + (dymatrix &arr) //overloading addition.
{
if (rows !=arr.rows && columns != arr.columns)
{
cerr<<"SIZE DO NOT MATCH, YOU FAIL"<<endl; exit(1);
}
dymatrix new_matrix(rows,columns);
for (int j = 0; j < arr.rows*arr.columns; j++)
{
//for (int i = 1; i <= arr.columns; i++)
//{
//cout<<"****"<<j<<endl;
new_matrix.matrix[j]= matrix[j]+arr.matrix[j]; //Putting in the data into this dynamic array for each element.
//}
}
return new_matrix;
}
This is my int main:
int main()
{
dymatrix a1;
cin >> a1; //Define the rows of the matrix
cout << a1<<endl<<endl;
dymatrix a2;
cin >> a2;
cout << a2<<endl<<endl;
dymatrix resu_a1;
resu_a1=a1+a2;
cout<<"Addition = "<<resu_a1<<endl;
dymatrix resu_a3;
resu_a3 = a1;
cout<<"Assigning = "<<resu_a3<<endl;
return 0;
}
You are returning copies of your matrix when you call operator +, but your dymatrix lacks a user-defined copy constructor:
dymatrix(const dymatrix&); // this is the missing function
You must implement this function to have a return-by-value of your dymatrix to be correct. Without this function, your code will exhibit undefined behavior, and will more than likely crash when it comes time to object destruction (double deletion errors and/or memory leaks).
Look up the "Rule of 3". If you implement a user-defined assignment operator, then a user-defined copy constructor and destructor should also be implemented:
What is The Rule of Three?
The easiest way to do this is to move most (if not all) of that code from your operator=, to the copy constructor. Then implement your operator= in terms of the copy constructor using the copy/swap idiom:
What is the copy-and-swap idiom?
As to your implementation of operator=: why are you doing all of that work to copy from one array to another? It should be a straight loop, going from 0 to rows*columns. You shouldn't need to call all of those extraneous functions to get the index and so forth.
But going back to the copy constructor, it would more than likely look like this:
#include <algorithm>
//...
dymatrix::dymatrix(const dymatrix& arr) :
rows(arr.rows), columns(arr.columns),
matrix(new double[arr.rows * arr.columns])
{
std::copy(arr.matrix, arr.matrix + rows*columns, matrix);
}
Now your assignment operator can be coded like this:
#include <algorithm>
//...
class dymatrix {
//...
dymatrix& operator=(dymatrix arr); // use this version of assignment operator
//...
};
//...
dymatrix& dymatrix::operator=(dymatrix arr)
{
std::swap(rows, arr.rows);
std::swap(columns, arr.columns);
std::swap(matrix, arr.matrix);
return *this;
}
The other point is that you should have implemented operator+= before you implemented operator +. The reason is that you could then write operator + in terms of operator +=, thus creating two operators, with operator + being essentially a 3 line function (the code in your current operator + would be moved to the operator +=.
Another point is that your operator+ should pass a const dymatrix&, instead of dymatrix&. You are not changing the parameter within the function, so it should be passed as const reference.
The last point is that if the matrices are not the same size when you add them, your code should throw an exception -- it should never just exit the program as your code is doing, and especially not within a class.
This should explain why you should never do this (I know it is probably a school exercise, but it is such a poor thing to do):
exit() call inside a function which should return a reference

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.

Operator Overloading

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=.