I have a program that is suppose to add together two matrices but when it gets to the add part in the main it just gets stuck and does nothing. I have messed with this for quite some time but to no avail. Any help or recommendations would be appreciated.
#include <iostream>
using namespace std;
class matrix
{
private:
int **p, m, n;
public:
matrix(int row, int col)
{
m = row;
n = col;
p = new int*[m];
for (int i = 0; i < m; i++)
p[i] = new int[n];
}
~matrix()
{
for (int i = 0; i < m; i++)
delete p[i];
delete p;
}
void fill()
{
cout<<"Enter the matrix elements:";
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
cin >> p[i][j];
}
}
}
void display()
{
cout <<"The matrix is:";
for(int i = 0; i < m; i++)
{
cout << endl;
for(int j = 0; j < n; j++)
{
cout << p[i][j] <<" ";
}
}
cout << endl;
}
matrix operator +(matrix m2)
{
matrix T(m, n);
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
T.p[i][j] = p[i][j] + m2.p[i][j];
}
}
return T;
}
matrix operator =(matrix eq)
{
m = eq.m;
n = eq.n;
p = eq.p;
return *this;
}
friend matrix operator *(matrix, matrix);
};
matrix operator *(matrix a , matrix b)
{
matrix B(1,1);
if(a.n == b.m)
{
matrix T(a.m, b.n);
for(int i = 0; i < a.m; i++)
{
for(int k = 0; k < b.n; k++)
{
T.p[i][k] = 0;
for(int j = 0; j < a.n; j++)
{
T.p[i][k]+= a.p[i][j] * b.p[j][k];
}
}
}
B = T;
}
return B;
}
int main()
{
matrix a(3,3), b(3,3);
a.fill();
a.display();
b.fill();
b.display();
cout << "addition of a and b\n";
b = b + a;
b.display();
cout << "multiplication of a and b\n";
b = (a * b);
b.display();
}
Your program is violating the rule of big three: it has a destructor but no assignment operator and no copy constructor. It keeps the data using raw pointers, but it's not managing proper ownership with copies are done and assignments are performed.
When your matrix class is copied and assigned your program is entering the Undefined Behavior territory so anything can happen. In this code copy construction is done implicitly when passing a matrix parameter by value, and assignment is done explicitly in main.
Related
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 2 years ago.
I am trying to write a matrice class in c++ with a overloaded + operator that is a friend function for summing a matrix with a number, ie sum every element of the matrice with the number.
for example:-
2+ |1|2| = |3|4|
|2|1| |4|3|
main.cpp :-
#include <iostream>
using namespace std;
class matrice {
int** a;
int rows, columns, i, j;
public:
matrice() {}
matrice(matrice& A) { //copy constructor for deep copying the result of 2+A into C
rows = A.rows;
columns = A.columns;
a = new int* [rows];
for (i = 0; i < rows; i++) {
a[i] = new int[columns];
*a[i] = 0;
}
for (i = 0; i < rows; i++) {
for (j = 0; j < columns; j++) {
a[i][j] = A.a[i][j];
}
}
}
matrice(int m, int n) {
rows = m;
columns = n;
a = new int* [rows];
for (i = 0; i < rows; i++) {
a[i] = new int[columns];
*a[i] = 0;
}
}
~matrice() {
delete[] a;
}
void insert(int p, int q, int value) {
a[p][q] = value;
}
void print() {
for (i = 0; i < rows; i++) {
cout << "\n";
for (j = 0; j < columns; j++) {
cout << a[i][j] << " ";
}
}
}
friend matrice operator+(int k, matrice& A);
friend matrice operator+(matrice& A, int k);
};
matrice operator+(int k, matrice& A) { //for performing 2+A
matrice temp(A.rows, A.columns);
for (int i = 0; i < A.rows; i++) {
for (int j = 0; j < A.columns; j++) {
temp.a[i][j] = A.a[i][j] + k;
}
}
return temp;
}
matrice operator+(matrice& A, int k) { //for performing A+2
matrice temp(A.rows, A.columns);
for (int i = 0; i < A.rows; i++) {
for (int j = 0; j < A.columns; j++) {
temp.a[i][j] = A.a[i][j] + k;
}
}
return temp;
}
int main() {
int i, j, m, n, value;
cout << "\nEnter order of A matrice:";
cin >> m >> n;
matrice A(m, n);
cout << "\nEnter the matrice:";
for (i = 0; i < m; i++) {
cout << "\nEnter row " << i + 1 << " : ";
for (j = 0; j < n; j++) {
cin >> value;
A.insert(i, j, value);
}
}
cout << "\nThe entered matrice is :";
A.print();
cout << "\n\n";
cout << "\nEnter order of B matrice:";
cin >> m >> n;
matrice B(m, n);
cout << "\nEnter the matrice:";
for (i = 0; i < m; i++) {
cout << "\nEnter row " << i + 1 << " : ";
for (j = 0; j < n; j++) {
cin >> value;
B.insert(i, j, value);
}
}
cout << "\nThe entered matrice is :";
B.print();
cout << "\n\ntesting 2+A";
matrice C; //Everything upto here is fine
C = A + 2; // C.a is pointing to unreadable memory because of destruction after doing A+2
C.print(); // so access violation error
}
The problem is that the destructor of C is called after invoking the copy constructor which causes the double pointer a in C to be deleted. So when C.print() is called An Access violation reading location 0xDDDDDDDD exception is thrown.
I can't find out why C's destructor is called.
The rule of 5 says that if you manually handle allocations, you should have an explicit (or explicitely deleted):
copy constructor
copy assignment operator
move constructor
move assignement operator
destructor
You might omit the ones that you are sure that you code will never use, but it is highly dangerous.
Anyway correct allocation/de-allocation handling is complex and requires very cautious code. For example the correct declaration for a copy ctor should be matrice(const matrice& A), and comments already warned you of memory leaks.
So my advice is:
if you want to learn about manual allocation management, follow best practices: rule of 5 an copy/swap idiom to avoid caveats
if you just want working code, replace 1D dynamic arrays with vectors and let the standard library handle the corner cases
A great deal of unexpected numbers outputted on my console window when I compiled and ran the program.
The class "matrix" is declared as below:
class matrix
{
public:
vector<vector<int> > M;
matrix();
matrix(int m, int n);
matrix(vector<vector<int> > &m);
matrix Mul(matrix m1);
void Inverse();
bool SquareMatrix();
void GetDet();
int Det(vector<vector<int> > &m);
void Print();
};
the member function "Mul":
matrix matrix::Mul(matrix m1)
{
vector<vector<int> > Temp(M.size(), vector<int>(m1.M[0].size(), 0));
if (M[0].size() != m1.M.size())
{
cout << "Cannot do multiplication!" << endl;
return matrix();
}
else
{
for (int i = 0; i < M.size(); i++)
{
for (int j = 0; j < m1.M[0].size(); j++)
{
int ele_buf = 0;
for (int k = 0; k < M[0].size(); k++)
{
ele_buf += M[i][k] * m1.M[k][j];
}
Temp[i][j] = ele_buf;
}
}
}
int d1 = M.size(), d2 = m1.M[0].size();
for (int i = 0; i < M.size(); i++)
{
M[i].clear();
}
M.clear();
M.resize(Temp.size(), vector<int>(Temp[0].size(), 0));
for (int i = 0; i < d1; i++)
{
for (int j = 0; j < d2; j++)
{
M[i][j] = Temp[i][j];
}
}
}
M[i][j] hold the expected value at this point.
the member function "Print":
void matrix::Print()
{
for (int i = 0; i < M.size(); i++) {
for (int j = 0; j < M[0].size(); j++) {
cout << M[i][j] << " ";
}
cout << endl;
}
}
Output wrong M.
main:
/*
call constructor to initialize m1 and m2
*/
//...
matrix m3 = m1.Mul(m2);
m3.Print();
//...
How can I fix it?
I'm new here, plz let me know if I didn't make my question clear.
Editted:
matrix matrix::Mul(matrix m1)
{
vector<vector<int> > Temp(M.size(), vector<int>(m1.M[0].size(), 0));
if (M[0].size() != m1.M.size())
{
cout << "Cannot do multiplication!" << endl;
return matrix();
}
else
{
//TO_DO: Multiply two matrixes and print the result.
for (int i = 0; i < M.size(); i++)
{
for (int j = 0; j < m1.M[0].size(); j++)
{
int ele_buf = 0;
for (int k = 0; k < M[0].size(); k++)
{
ele_buf += M[i][k] * m1.M[k][j];
}
Temp[i][j] = ele_buf;
}
}
}
int d1 = M.size(), d2 = m1.M[0].size();
for (int i = 0; i < M.size(); i++)
{
M[i].clear();
}
M.clear();
return matrix(Temp);
}
Functionning properly,
thanks.
You forgot to add a return statement, which is trivial to fix. However, your code is not written in a good OO manner, so here come few suggestions for the improvement:
don't pass matrix m1 by value, because you are paying an expensive copy each time you invoke this function; use const matrix& m1 instead
in the body of Mul you are modifying member M, which is a serious side effect; remove the part of code:
int d1 = M.size(), d2 = m1.M[0].size();
for (int i = 0; i < M.size(); i++)
{
M[i].clear();
}
M.clear();
instead of implementing a separate function called Mul, overload the * operator (see e.g. here and here)
You are promised to return matrix from the Mul function
matrix matrix::Mul(matrix m1);
^^^^^^
and you did not keep the promise. This can cause undefined behaviour to your program.
Add an proper return statement in the function.
matrix matrix::Mul(matrix m1)
{
// ... code
return *this; // matrix(Temp) itself
}
This is supposed to be my HW in OOP course. SO i asked to create matrix class. Code works fine - all methods and new operands works fine BUT when my D`tor is empty and when i write there code to free memory i get this error. Thanks for help
int main()
{
MyMatrix m1(3, 3);
MyMatrix m2(3, 3);
MyMatrix res(3, 3);
m1.Set();
m2.Set();
cout << m1;
cout << m2;
res = m1 + m2;
cout << res;
}
CPP
MyMatrix::MyMatrix(int row, int col) // C`tor with specific data
{
n = row;
m = col;
matrix = new int* [n]; // Memory allocation for rows
for (int i = 0; i < n; i++)
{
matrix[i] = new int[m]; // Memory Allocation for columns
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = 0;
}
}
}
MyMatrix::~MyMatrix() // Default d`tor
{
for (int i = 0; i < n; i++)
{
delete[] matrix[i];
}
delete[] matrix;
}
void MyMatrix::Set()
{
cout << "Enter new row" << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cin >> matrix[i][j];
}
if (i != (n - 1))
{
cout << "Enter new row" << endl;
}
}
}
ostream& operator<<(ostream& out, const MyMatrix& matrix)
{
for (int i = 0; i < matrix.n; i++)
{
//run in loop on every column.
for (int j = 0; j < matrix.m; j++)
//print value with a space.
out << matrix.matrix[i][j] << "t";
//at the end of every row jump line.
out << endl;
}
out << endl;
return out;
}
MyMatrix& MyMatrix::operator= (const MyMatrix& mat1)
{
n = mat1.n;
m = mat1.m;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
matrix[i][j] = mat1.matrix[i][j];
}
}
return *this;
}
const MyMatrix MyMatrix::operator+(const MyMatrix& mat1) const
{
MyMatrix temp(n, m);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
temp.matrix[i][j] = matrix[i][j] + mat1.matrix[i][j];
}
}
return temp;
}
H file
class MyMatrix
{
private:
int **matrix;
int n, m;
public:
MyMatrix(int a, int b);
~MyMatrix();
void Set();
const MyMatrix operator+ (const MyMatrix& mat1) const;
MyMatrix& operator= (const MyMatrix& mat1);
friend ostream& operator<<(ostream& out, const MyMatrix& matrix);
};
i am working on multiplication of matrix
it is something like
m5 = m2 * m3;
cout << "m2 * m3 is : " << endl<< m5 << endl;
and this is my code
const Matrix Matrix::operator*(const Matrix &a)
{
Matrix temp(a.row,a.col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
for (int k = 0; k<a.row; k++)
{
temp.data[i][j] = temp.data[i][j] + data[i][k] * a.data[k][j];
}
}
}
return temp;
}
However, there is an error always showing at my printing function
ostream& operator<<(ostream &output, const Matrix &a)
{
for (int i = 0; i < a.row; i++)
{
for (int j = 0; j < a.col; j++)
{
output << a.data[i][j] << "\t";
}
output << "" << endl;
}
return output;
}
seems there has a problem on a.data[i][j] which i dont know what's the problem
it works fine on addition.
it is showing an error {data0x005fba90{0xfeeefeee{???}}
can anybody give any advice or suggestions or help on this situation
this is my copy constructor
Matrix::Matrix(const Matrix&m2)
{
row = m2.row;
col = m2.col;
setUp(row, col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = m2.data[i][j];
}
}
}
this is the set up and default
Matrix::Matrix()
{
row =0;
col = 0;
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
}
Matrix::Matrix(int a, int b, double d[], int c)
{
row = a;
col = b;
setUp(row, col);
int counter = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = d[counter];
counter++;
}
}
}
and the set up
void Matrix::setUp(int a, int b)
{
row = a;
col = b;
data = new double*[row];
for (int i = 0; i < row; i++) data[i] = new double[col];
}
Without seeing your Matrix constructor, or the class definition, it's hard to say for certain, but if you look at this expression
temp.data[i][j] + data[i][k] * a.data[k][j]
Depending on what data is, if you don't explicitly initialize the data member in the constructor when you create temp then its contents will not automatically be initialized, and the contents will be indeterminate and using it will lead to undefined behavior.
Another possible source of problems might be the lack of a copy-constructor, or a faulty copy-constructor. This is a problem since you return temp by value which invokes the copy-constructor.
I'm trying to implement a matrix class and overloading the + and = operators.
The problem is I'm getting weird output when I add two matrices as in this picture.
adding two matrices output console
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix
{
int **p, m, n;
public:
Matrix(int row, int col)
{
m = row;
n = col;
p = new int*[m];
for (int i = 0; i < m; i++)
p[i] = new int[n];
}
Matrix (Matrix & x)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
p[i][j]=x.p[i][j];
}
}
}
~Matrix()
{
for (int i = 0; i < m; i++)
delete [] p[i];
delete [] p;
}
void accept()
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
cin >> p[i][j];
}
}
}
void display()
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
cout << setw(10)<<left <<p[i][j] <<" | ";
}
cout << "\n--------------------------------------"<<endl;
}
}
Matrix& operator +(const Matrix & m2)
{
Matrix r(m, n);
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
r.p[i][j] = p[i][j] + m2.p[i][j];
}
}
return r;
}
Matrix& operator= (const Matrix & eq)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
p[i][j]=eq.p[i][j];
}
}
return *this;
}
friend Matrix operator * (Matrix, Matrix);
};
Matrix operator* (Matrix a , Matrix b)
{
Matrix B(1,1);
if(a.n == b.m)
{
Matrix T(a.m, b.n);
for(int i = 0; i < a.m; i++)
{
for(int k = 0; k < b.n; k++)
{
T.p[i][k] = 0;
for(int j = 0; j < a.n; j++)
{
T.p[i][k]+= a.p[i][j] * b.p[j][k];
}
}
}
B = T;
}
return B;
}
int main()
{
cout << "Enter Matrix 1 (3x2):"<<endl;
Matrix m1(3,2);
m1.accept();
m1.display();
cout << "Enter Matrix 2 (3x2):"<<endl;
Matrix m2(3,2);
m2.accept();
m2.display();
Matrix m3(3,2);
m3=m1+m2;
cout <<endl<< "matrix1 + matix2 is:\n "<<endl;
m3.display();
}
Any ideas how to fix that? I would be grateful for your help and advices with improving it because probably there will be some mistakes.
I use CodeBlocks IDE.
The problem is that your operator + returns a local variable Matrix as a reference; this is undefined behavior. It should be returned by value, not by reference.
Make sure that your Matrix class has a copy constructor that takes a const input, i.e.
Matrix (const Matrix & x)
and that it initializes the array before writing into it. Move the initialization code (the two loops with allocation) into a separate private function, and call it from the default constructor and from the copy constructor.