c++ empty copy assignment operator copies data - c++

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.

Related

Efficient matrix implementation

I have the following problem:
I've a precomputed 2d matrix of values which i need to lookup very often and compute only once
The size of the matrix is about 4000x4000 at most
The matrix won't be sparse, i typically need almost all values.
The values in the matrix can be boolean, integer or double. At least they are always small objects
Currently i am storing the precomputed values in a std::vector<<std::vector<T>>, and i've noticed the lookups into this datastructure takes quite some time in heavy computations. I've googled around and so far the suggested implementation seems to be to try a solution in which all the memory is stored contigious using an 1D array where the location in this array is computed based on i and j.
Does anybody have a good example implementation of this or has an even better suggestion? I couldn't find a modern C++ example, while it seems to be a very common problem to me. I'd prefer to use someone elses code instead of reinventing the wheel here. Of course i will measure the differences to see whether it actually improves performance.
Examples i've found:
https://medium.com/#patdhlk/c-2d-array-a-different-better-solution-6d371363ebf8
https://secure.eld.leidenuniv.nl/~moene/Home/tips/matrix2d/
Here is a very simple and efficient 2-d matrix. The 'main' creates a 10000x10000 double array 'mat', then filled it with random number. The array 'mat' is copied into another array 'mat2'. your may input two integers 'n' and 'm' between 0 and 9999 to fetch the double data at mat2(n,m).
Feel free to use or test it. Let me know if you encounter problems or need some more functions to be implemented. Good luck!
#ifndef ytlu_simple_matrix_class_
#define ytlu_simple_matrix_class_
#include <iostream>
#include <iomanip>
#include <complex>
template <typename T> class tMatrix
{
public:
T *ptr;
int col, row, size;
inline T* begin() const {return ptr;}
inline T* end() const {return this->ptr + this->size;}
inline T operator()(const int i, const int j) const { return ptr[i*col+j];
} // r-value
inline T&operator()(const int i, const int j) { return ptr[i*col+j]; } //l-value
inline tMatrix(): col{0}, row{0}, size{0}, ptr{0} {;}
tMatrix(const int i, const int j): col(j), row(i), size(i*j)
{
ptr = new T [this->size] ;
}
tMatrix(const tMatrix<T>&a) : tMatrix<T>(a.row, a.col)
{
std::copy(a.begin(), a.end(), this->ptr);
}
tMatrix<T>& operator=(tMatrix<T>&&a)
{
this->col = a.col;
this->row = a.row;
delete [] this->ptr;
this->ptr = a.ptr;
a.ptr = nullptr;
return *this;
}
tMatrix<T>& operator=(const tMatrix<T>&a)
{
if (col==a.cpl && row==a.row) std::copy(a.begin(), a.end(), this->ptr);
else { tMatrix<T>&&v(a); *this = std::move(v);}
return *this;
}
~tMatrix() {delete [] this->ptr;}
}; //end of class tMatrix
template <typename X> std::ostream& operator<<(std::ostream&p, const tMatrix<X>&a)
{
p << std::fixed;
for (int i=0; i<a.row; i++) {
for (int j=0; j <a.col; j++) p << std::setw(12) << a(i, j);
p << std::endl;
}
return p;
}
using iMatrix = tMatrix<int>;
using rMatrix = tMatrix<double>;
using cMatrix = tMatrix<std::complex<double> >;
#endif
//
//
#include <ctime>
#include <cstdlib>
#define N1 10000
int main()
{
int n, m;
std:srand(time(NULL)); // randomize
rMatrix mat(N1, N1); // declare a 10000 x 10000 double matrix
//
// fill the whole matrix with double random number 0.0 - 1.0
//
for (int i = 0; i<mat.row; i++)
{ for (int j=0; j<mat.col; j++) mat(i, j) = (double)std::rand() / (double)RAND_MAX; }
//
// copy mat to mat 2 just for test
//
rMatrix mat2 = mat;
//
// fetch data test input 0 <= n m < 10000 to print mat2(n, m)
//
while(1)
{
std::cout << "Fetch 2d array at (n m) = ";
std::cin >> n >> m;
if ((n < 0) || (m < 0) || (n > mat2.row) || (m > mat2.col) )break;
std::cout << "mat(" << n << ", " << m << ") = " << mat2(n, m) << std::endl << std::endl;
}
return 0;
}
The compile parameter I used and the test run. It takes a couple seconds to fill the random numbers, and I felt no lapse at all in fetch a data running in my aged PC.
ytlu#ytlu-PC MINGW32 /d/ytlu/working/cpptest
$ g++ -O3 -s mtx_class.cpp -o a.exe
ytlu#ytlu-PC MINGW32 /d/ytlu/working/cpptest
$ ./a.exe
Fetch 2d array at (n m) = 7000 9950
mat(7000, 9950) = 0.638447
Fetch 2d array at (n m) = 2904 5678
mat(2904, 5678) = 0.655934
Fetch 2d array at (n m) = -3 4

why my function doesn't change my object's attribute

I'm trying to do a Matrix class using C++ Vector, but i don't know why the inside of "Matrix result" inside my function isn't passed to my object but it remain enclosed inside the function.
for semplicity so far I've tryed only to do an "addition function" among two Matrices.
I have tryied to work with pointer but in this way (according to my knowledgs) i cant call my funtion to an object in this wise:
foo.function1(bar1).function2(bar2);
but working with pointer i have to call function in this manner:
foo.function1(bar1);
foo.function2(bar2);
//and so on..
this is my header file:
#include <iostream>
#include <vector>
using namespace std;
class Matrix
{
public:
Matrix (int height, int width);
Matrix add(Matrix m);
Matrix applyFunction(double (*function)(double));
void print();
private:
vector<vector<double> > matrix;
int height;
int width;
};
this is the .cpp file:
Matrix::Matrix(int height, int width)
{
this->height = height;
this->width = width;
this->matrix = vector<vector<double> >(this->height, vector<double>(this->width));
}
Matrix Matrix::add(Matrix m)
{
Matrix result(this->height, this->width);
if (m.height== this->height&& m.width== this->width)
{
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
result.matrix[i][j] = this->matrix[i][j] + m.matrix[i][j];
}
return result;
}
}
else
{
cout << "Impossible to do addition, matrices doesn't have the same dimension" << endl;
return result;
}
}
Matrix Matrix::applyFunction(double(*function)(double))
{
Matrix result(this->height, this->width);
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
result.matrix[i][j] = (*function)(this->matrix[i][j]);
}
}
return result;
}
void Matrix::print()
{
for (int i = 0; i < this->height; i++)
{
for (int j = 0; j < this->width; j++)
{
cout << this->matrix[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
the output should be the addition beetwen A B 2x2:
x1 x2
x3 x4
but computer show only zeros.
Your member functions all return a new object (they return "by value").
From your usage of chaining, it seems like you actually want to modify the object and return *this by reference.
Otherwise you'll need something like:
auto bar2 = foo.function1(bar1);
auto bar3 = foo.function2(bar2);
// etc
There are no pointers here at present.
There are two variants how you can implement your add
Matrix add(Matrix m)
{
// optimisation: you don't need separate result, m already IS a copy!
// so you can just calculate:
...
{
m.matrix[i][j] += this->matrix[i][j];
}
return m;
}
or:
Matrix& add(Matrix const& m)
// ^ accept const reference to avoid unnecessary copy
// ^ returning reference(!)
{
...
{
// modifies itself!
this->matrix[i][j] += m.matrix[i][j];
}
return *this; // <- (!)
}
This allows now to do:
Matrix m0, m1, m2;
m0.add(m1).add(m2);
// m0 now contains the result, original value is lost (!)
So you don't need the final assignment as in first variant:
m0 = m0.add(m1).add(m2);
// or assign to a new variable, if you want to retain m0's original values
which is what you lacked in your question (thus you did not get the desired result).
Maybe you want to have both variants, and you might rename one of. But there's a nice feature in C++ that you might like even better: Operator overloading. Consider ordinary int:
int n0, n1;
n0 += n1;
int n2 = n0 + n1;
Well, suppose you know what's going on. And if you could do exactly the same with your matrices? Actually, you can! You need to do is overloading the operators:
Matrix& operator+=(Matrix const& m)
{
// identical to second variant of add above!
}
Matrix operator+(Matrix m) // again: the copy!
{
// now implement in terms of operator+=:
return m += *this;
}
Yes, now you can do:
Matrix m0, m1, m2;
m0 += m1 += m2;
m2 = m1 + m0;
Alternatively (and I'd prefer it) you can implement the second operator (operator+) as free standing function as well:
// defined OUTSIDE Matrix class!
Matrix operator+(Matrix first, Matrix const& second)
{
return first += second;
}
Finally: If dimensions don't match, better than returning some dummy matrix would be throwing some exception; std::domain_error might be a candidate for, or you define your own exception, something like SizeMismatch. And please don't output anything to console or elsewhere in such operators, this is not what anybody would expect from them, additionally, you impose console output to others who might consider it inappropriate (perhaps they want output in another language?).

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

Multiplying arrays

How can I get the Matrix overloaded constructor to combine Vector a and Vector b to form a Matrix object as an outer product. And do the same for Vector c and Vector d. The problem is with overloaded constructor and being able to use that create a matrix. At the moment it can only use Vector a and Vector b when it needs to use each. The print member function needs to print the Matrix from the users input values.
#include <iostream>
using namespace std;
const int rows=3;
const int columns=3;
const int elements=3;
class Vector{
private:
double data[elements];
public:
Vector();
void read();
double get_element(int);
};
Vector::Vector(){
int i=0;
while(i<elements){data[i++]=0;}
}
void Vector::read(){
int j=0;
cout<<"Enter "<<elements<<" elements of vector "<<endl;
while(j<elements){cin>>data[j++];}
}
double Vector:: get_element(int n){
while(n<elements)
return data[n];
}
Vector a,b,c,d;
class Matrix {
private:
double data [rows*columns];
public:
Matrix(Vector &, Vector &);
void add (const Matrix &);
void mult (double);
double trace();
double norm();
void print ();
};
Matrix::Matrix(Vector &, Vector &){
int d,f;
for (d=0; d<rows; d++){
for (f=0; f<columns;f++){
data[d*f]=a.get_element(d)*b.get_element(f);
}
}
}
Matrix A (a, b);
Matrix B (c, d);
void Matrix::print(){
cout.setf(ios::showpoint|ios::fixed);
cout.precision(3);
for (int i=0; i<rows; i++) {
cout << endl;
for (int j=0; j<columns; j++) {
cout << " " << data[i*j];
}
}
}
First thing is first, get rid of the using namespace std. You don't want to import all of std into your class just to use cout and cin.
Now lets get to the basics. You have a class which is supposed to encapsulate/hold data of its own. This class can be passed around and be worked on. Each class has its own unique set of data for your vector/matrix class.
In the above, you have your classes using global variables. This is bad because every vector will have the same exact data. They all share the same variables (global)!
Thus we need to put somehow get Vector to contain its own data. We do this by putting the variable inside the vector class itself. We make it private so that it cannot be accessed outside of the class.
Next, we need a way to initialize data. We cannot give it elements anymore because elements is no longer going to be global and constant. Thus we must now dynamically allocate elements amount of doubles in the constructor and delete it in the destructor.
To prevent weird behavior for now, we disallow copying and assigning. You should REALLY take look at a tutorial on classes and encapsulation.. This answer will be pretty incomplete but should help somewhat and fix a couple things..
If you are 100% sure that vector MUST ONLY have 3 elements, nothing more, nothing less, then you may change double* data to double data[3] and remove new data[...] from the constructor and delete[] data from the destructor.
#include <iostream>
class Vector
{
private:
double* data; //will point to an array of elements.
int elements; //amount of elements this vector has.
Vector(const Vector& other); //copying not allowed.
Vector& operator = (const Vector& other); //copy assignment not allowed.
public:
Vector(int elements); //constructor that tells us how large of an array we need.
~Vector(); //destructor to delete the dynamically allocated array when done.
int size() const; //returns the amount of elements.
double get_element(int n) const;
void set_element(double value, int index);
};
//This is our constructor. It stores the amount of elements we allocated within our class.
//It also initialises data to point to the `new` array.
Vector::Vector(int elements_) : elements(elements_), data(new double[elements_]())
{
}
Vector::~Vector()
{
delete[] data; //before the class gets destroyed, we clean up our dynamically allocated array. ALWAYS!
}
double Vector::get_element(int n) const
{
return data[n];
}
void Vector::set_element(double value, int index)
{
data[index] = value;
}
int Vector::size() const
{
return elements;
}
/** We do the same for the matrix class.**/
class Matrix
{
private:
double* data;
int rows, columns; //instead of elements, we have rows and columns.
Matrix (const Matrix &other); //prevent copying.
Matrix& operator = (const Matrix &other); //prevent assignment.
public:
Matrix(const Vector &a, const Vector &b); //constructor takes TWO vectors.
~Matrix();
void add (const Matrix&);
void mult (double);
double trace();
double norm();
void print ();
};
/** Data is initialized to an array of doubles[rows * columns] **/
/** We also store the amount of rows and columns allocated **/
Matrix::Matrix(const Vector &a, const Vector &b) : data(new double[a.size() * b.size()]), rows(a.size()), columns(b.size())
{
int d, f;
for (d = 0; d < rows; d++)
{
for (f = 0; f < columns; f++)
{
data[d * f] = a.get_element(d) * b.get_element(f);
}
}
}
Matrix::~Matrix()
{
delete[] data; //Before the class is destroyed, we must delete the array.
}
void Matrix::print()
{
std::cout.setf(std::ios::showpoint | std::ios::fixed);
std::cout.precision(3);
for (int i = 0; i < rows; i++)
{
std::cout << std::endl;
for (int j = 0; j < columns; j++)
{
std::cout << " " << data[i * j];
}
}
}
int main()
{
Vector a(3); //Now we can a vector.
Vector b(3); //another vector.
Vector c(2); //notice we can choose how many elements the vector can hold.. 2 elements = a point. Nevertheless..
a.set_element(5.0d, 0);
b.set_element(10.0d, 2);
Matrix m(a, b); //Create a matrix from our two vectors.
m.print(); //Print it..
}
As said before, if you are 100% sure that all matrices are 3x3 and all vectors have 3 elements only, then the following is what the class would look like:
#include <iostream>
class Vector
{
private:
static const int elements = 3; //static. All vector instances will have the same amount of elements.
double data[elements]; //stack allocation. 3 elements only.
Vector(const Vector& other);
Vector& operator = (const Vector& other);
public:
Vector();
~Vector();
void read();
int size() const;
double get_element(int n) const;
};
Vector::Vector() : data() {} //nothing in the constructor. data is filled with 0's.
Vector::~Vector() {} //nothing to delete in the destructor..
double Vector::get_element(int n) const
{
return data[n];
}
int Vector::size() const
{
return elements;
}
class Matrix
{
private:
static const int rows = 3, columns = 3; //all matrix instances will have 3 rows, 3 columns.
double data[rows * columns];
Matrix (const Matrix &other);
Matrix& operator = (const Matrix &other);
public:
Matrix(const Vector &a, const Vector &b);
~Matrix();
void add (const Matrix&);
void mult (double);
double trace();
double norm();
void print ();
};
Matrix::Matrix(const Vector &a, const Vector &b) //nothing to allocate in the constructor.
{
for (int d = 0; d < rows; d++)
{
for (int f = 0; f < columns; f++)
{
data[d * f] = a.get_element(d) * b.get_element(f);
}
}
}
Matrix::~Matrix() {} //nothing to delete in the destructor.
void Matrix::print()
{
std::cout.setf(std::ios::showpoint | std::ios::fixed);
std::cout.precision(3);
for (int i = 0; i < rows; i++)
{
std::cout << std::endl;
for (int j = 0; j < columns; j++)
{
std::cout << " " << data[i * j];
}
}
}
int main()
{
Vector a;
Vector b;
Matrix m(a, b);
m.print();
}

C++ Scope Resolution Issue

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