I'm writting some code for teaching myself C++.
Does the following code:
#include <iostream>
using namespace std;
class Matrix
{
int m, n;
public:
float** value;
Matrix(int m, int n)
{
value = new float*[m];
for (int i = 0; i < m; ++i)
value[i] = new float[n];
this->m = m; this->n = n;
}
~Matrix()
{
for (int i = 0; i < m; ++i)
delete[] value[i];
delete[] value;
}
Matrix(const Matrix& A)
{
m = A.getLength();
n = A.getWidth();
value = new float*[m];
for (int i = 0; i < m; ++i)
value[i] = new float[n];
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
value[i][j] = A.value[i][j];
}
int getLength(void) const
{
return m;
}
int getWidth(void) const
{
return n;
}
void print() const
{
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
cout << value[i][j] << "\t";
cout << endl;
}
}
Matrix operator + (const Matrix& B)
{
if (m != B.getLength() || n != B.getWidth())
return Matrix(0, 0);
Matrix C = Matrix(m, n);
cout << value << endl;
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
C.value[i][j] = value[i][j] + B.value[i][j];
return C;
}
void operator = (const Matrix& A)
{
m = A.getLength();
n = A.getWidth();
value = new float*[m];
for (int i = 0; i < m; ++i)
value[i] = new float[n];
for (int i = 0; i < m; ++i)
for (int j = 0; j < n; ++j)
value[i][j] = A.value[i][j];
}
};
int main()
{
Matrix A = Matrix(3, 3);
A.value[0][0] = 1; A.value[0][1] = 2; A.value[0][2] = 3;
A.value[1][0] = 4; A.value[1][1] = 5; A.value[1][2] = 6;
A.value[2][0] = 7; A.value[2][1] = 8; A.value[2][2] = 9;
Matrix B = Matrix (3, 3);
B.value[0][0] = 1; B.value[0][1] = 2; B.value[0][2] = 3;
B.value[1][0] = 4; B.value[1][1] = 5; B.value[1][2] = 6;
B.value[2][0] = 7; B.value[2][1] = 8; B.value[2][2] = 9;
Matrix C = A + B;
cout << C.value << endl;
C.print();
return 0;
}
Generate a memory leak at the part "Matrix C = A + B"? I don't know if the returned matrix is destroyed after the association is done. If yes, is there a way to fix it?
In statement
Matrix C = A + B;
there is no leak.
Though in your code the copy assignment operator is not used nevertheless your copy assignment operator does not free the memory previously allocated to the matrix of an object.
The copy assignment operator differs from the copy constructor in that that the object is already created and has an allocated matrix. Also you have to check whether there is the self assignment.
Also it should be declared as
Matrix & operator = (const Matrix& A)
As for operator + then it should be declared as
Matrix operator + (const Matrix& B) const;
or as
const Matrix operator + (const Matrix& B) const;
Related
I implement the overloading of the addition and multiplication operators for the matrix class. I can't understand where the error is, or rather, I guess that there is an error in the declaration of operators, but I have no idea how to fix it specifically.
Can someone suggest a good book on object oriented programming. I feel that I am clearly lacking information
#include <iostream>
using namespace std;
template <typename T>
class MATRIX
{
private:
T** M;
int m;
int n;
public:
MATRIX()
{
n = m = 0;
M = nullptr;
}
MATRIX(int _m, int _n)
{
m = _m;
n = _n;
M = (T**) new T * [m];
for (int i = 0; i < m; i++)
M[i] = (T*)new T[n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
M[i][j] = 0;
}
MATRIX(const MATRIX& _M)
{
m = _M.m;
n = _M.n;
M = (T**) new T * [m];
for (int i = 0; i < m; i++)
M[i] = (T*) new T[n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
M[i][j] = _M.M[i][j];
}
T GetMij(int i, int j)
{
if ((m > 0) && (n > 0))
return M[i][j];
else
return 0;
}
void SetMij(int i, int j, T value)
{
if ((i < 0) || (i >= m))
return;
if ((j < 0) || (j >= n))
return;
M[i][j] = value;
}
void Print(const char* ObjName)
{
cout << "Object: " << ObjName << endl;
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
cout << M[i][j] << "\t";
cout << endl;
}
cout << "---------------------" << endl << endl;
}
MATRIX operator=(const MATRIX& _M)
{
if (n > 0)
{
for (int i = 0; i < m; i++)
delete[] M[i];
}
if (m > 0)
{
delete[] M;
}
m = _M.m;
n = _M.n;
M = (T**) new T * [m];
for (int i = 0; i < m; i++)
M[i] = (T*) new T[n];
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++)
M[i][j] = _M.M[i][j];
return *this;
}
MATRIX operator+(const MATRIX& _M) {
MATRIX M6(_M.n, _M.m);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
M6.M[i][j] = _M.M[i][j]+this-> M[i][j];
}
return M6;
}
MATRIX operator*(const MATRIX& _M) {
MATRIX M5(_M.n, _M.m);
for (int i = 0; i < _M.n; i++)
{
for (int j = 0; j < _M.m; j++)
{
for (int k = 0; k < m; k++)
{
M5.M[i][j] += M[i][k]*_M.M[k][j];
}
}
}
return M5;
}
bool operator ==(const MATRIX& _M) {
return this->n == _M.n && this->m == _M.m;
}
bool operator !=(const MATRIX& _M) {
return !(this->n == _M.n && this->m == _M.m);
}
~MATRIX()
{
if (n > 0)
{
for (int i = 0; i < m; i++)
delete[] M[i];
}
if (m > 0)
delete[] M;
}
};
void main()
{
MATRIX<int> M(2, 3);
M.Print("M");
int i, j;
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
M.SetMij(i, j, i + j);
M.Print("M");
MATRIX<int> M2 = M;
M2.Print("M2");
MATRIX<int> M3;
M3 = M;
M3.Print("M3");
MATRIX<int> M4;
M4 = M3 = M2 = M;
M4.Print("M4");
////////////////////////
bool result = M == M3;// ==
if (result == 1) {
cout << "true";
}
else if (result == 0) {
cout << "false";
}
cout << endl << "---------------------" << endl << endl;
//////////////////////////
bool result1 = M != M3;// !=
if (result1 == 1) {
cout << "true";
}
else if (result1 == 0) {
cout << "false";
}
cout << endl << "---------------------" << endl << endl;
MATRIX<int> M1;
for (i = 0; i < 2; i++)
for (j = 0; j < 3; j++)
M1.SetMij(i, j, i + j);
M1.Print("M1");
M.Print("M");
MATRIX<int> M6 = M + M1;
M6.Print("M");
MATRIX<int> M5 = M * M1;
M5.Print("M");
}```
thanks in advance
[enter image description here][1]
[1]: https://i.stack.imgur.com/TjEOp.png
I belive that std::vector is better
MATRIX() {}
MATRIX(int r, int c) : M(r * c, T()) , rows(r), cols(c) { }
// Does not need copy constructor
// Does not need operator =
// Does not need destructor
also you can proxy row and cols to overload []
MATRIX<int> x(3,3);
x[2][2] = 10;
also a generating function is welcome
template<typename GenT> void generate( GenT gen ) {...}
https://godbolt.org/z/dK6Tqc
class Matrix
{
private:
int rows;
int cols;
int** Mat;
public:
Matrix(){}
Matrix(const int& rows, const int& cols):rows(rows),cols(cols)
{
Mat = new int* [cols];
for (int i = 0; i < rows; i++)
{
Mat[i] = new int[cols]();
}
}
Matrix operator +(const Matrix& other)const
{
Matrix temp(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
temp.Mat[i][j] += other.Mat[i][j] + Mat[i][j];
return temp;
}
My question is regarding how I'd use shared_ptr and make_shared to replace int** Mat? and, after that, how do I use it in the constructor and operator+? It's a custom matrix class that should add matrices
#include <iostream>
#include <memory>
#include <cassert>
class Matrix {
private:
int rows;
int cols;
std::shared_ptr<std::shared_ptr<int>> Mat;
public:
Matrix() = default;
Matrix(const int& rows, const int& cols) : rows(rows), cols(cols)
{
Mat.reset(new std::shared_ptr<int>[rows], [](std::shared_ptr<int>* p) { delete[] p; });
for (int i = 0; i < rows; ++i)
{
Mat.get()[i].reset(new int[cols], [](int* p) { delete[] p; });
}
for (int i = 0; i < (*this).rows; ++i)
for (int j = 0; j < (*this).cols; ++j)
(*this)[i][j] = 0;
}
int* operator[](const int& index) const
{
return Mat.get()[index].get();
}
Matrix(const Matrix& other) : cols(other.cols), rows(other.rows)
{
Mat.reset(new std::shared_ptr<int>[rows], [](std::shared_ptr<int>* p) { delete[] p; });
for (int i = 0; i < rows; ++i)
{
Mat.get()[i].reset(new int[other.cols], [](int* p) { delete[] p; });
}
for (int i = 0; i < other.rows; i++)
for (int j = 0; j < other.cols; j++)
(*this)[i][j] = other[i][j];
}
Matrix& operator=(const Matrix& other)
{
if (Mat != other.Mat && cols == other.cols && rows == other.rows)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
(*this)[i][j] = other[i][j];
return *this;
}
else
return *this;
}
Matrix operator+(const Matrix& other) const
{
Matrix temp(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
temp[i][j] += other[i][j] + (*this)[i][j];
return temp;
}
friend std::ostream& operator<<(std::ostream& os, Matrix& m)
{
for (int i = 0; i < m.rows; ++i)
{
for (int j = 0; j < m.cols; ++j)
{
os << m[i][j] << " ";
}
os << std::endl;
}
return os;
}
};
int main()
{
Matrix a(2, 2);
a[0][0] = 1;
a[0][1] = 1;
std::cout << a << std::endl;
Matrix b(2, 2);
b[1][1] = 1;
b[1][0] = 1;
std::cout << b << std::endl;
b[1][0] = 9;
Matrix c(a);
c[0][0] = 6;
std::cout << c << std::endl;
Matrix d = b;
std::cout << d << std::endl;
Matrix e = a + b;
std::cout << e << std::endl;
}
I have solved it myself in the end :D
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);
};
So I wrote this:
Matrix.h:
#pragma once
class Matrix
{
private:
int m, n;
double** M = nullptr;
public:
Matrix();
Matrix(int,int);
Matrix(const Matrix&);
~Matrix();
void set_m(int);
void set_n(int);
int get_m() const;
int get_n() const;
void setM(double**,int,int);
double** getM() const;
void show();
Matrix operator*(Matrix&) const;
};
Matrix.cpp:
#include "Matrix.h"
#include<iostream>
using namespace std;
/*
*/
Matrix::Matrix()
{
set_n(1);
set_m(1);
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(int m_,int n_)
{
set_n(n_);
set_m(m_);
delete[] M;
M = new double *[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(const Matrix& M_)
{
set_n(M_.get_n());
set_m(M_.get_m());
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = M_.getM()[i][j];
}
void Matrix::set_m(int m_) {
if (m_ > 0)
m = m_;
else
m = 1;
}
void Matrix::set_n(int n_) {
if (n_ > 0)
n = n_;
else
n = 1;
}
double** Matrix::getM() const {
return M;
}
Matrix Matrix::operator*(Matrix &M_) const
{
if (get_n() != M_.get_m()) {
if (get_m() != M_.get_n()) return Matrix();
else {
Matrix T(*this);
return M_*T;
}
}
else {
//n = m
Matrix R(get_m(), M_.get_n());
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < M_.get_n(); j++) {
double res = 0;
for (int k = 0; k < get_n(); k++) {
res += getM()[i][k] * M_.getM()[k][j];
}
R.getM()[i][j] = res;
}
}
return R;
}
}
int Matrix::get_m() const {
return m;
}
int Matrix::get_n() const {
return n;
}
void Matrix::setM(double** M_, int m_, int n_) {
set_m(m_);
set_n(n_);
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
M = new double*[m_];
for (int i = 0; i < m; i++) {
M[i] = new double[n_];
}
for (int i = 0; i < m_; i++)
for (int j = 0; j < n_; j++) M[i][j] = M_[i][j];
}
void Matrix::show() {
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < get_n(); j++) {
cout << getM()[i][j]<<" ";
}
cout << endl;
}
}
Matrix::~Matrix()
{
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
}
It crashes at void Matrix::setM(...) when I try to delete M[i] for i = 1; it doe perfectly fine for i=0; but crashes later and I do not have a rational explanation why does it do that. I can see the debugger showing me that the memory cannot be read even before it actually crashing but I do not understand how to fix it. Thanks in advance!
You are setting your m before deleting your array based on the old value of m and end up deleting your old array using the new value of m. You should first delete your array, then set mm, and then create your new array.
I have a University assignment whereby I have a 1D array, containing 262144 values. I've created a matrix class which places these values into an object with the datasource being the double* list of 262144 values.
I need to be able to obtain a sub-matrix (which I'm able to do) from ANOTHER set of 262144 values (which I've also placed into a matrix object).
However, I'm having serious trouble and I've been trying so hard for the last 3 days to try and replace original matrix values from a sub-matrix. I've tried passing by reference, creating Matrix*'s. I've tried everything we've been taught and even researched a few more methods, all of which I haven't understood. I'll throw my code in here to see if anyone can explain a method to me which will be able to do this.
Matrix::Matrix()
{
"Matrix::Matrix() is invoked";
}
Matrix::Matrix(const Matrix& m)
{
"Matrix::Matrix(const Matrix&) is invoked";
_M = m._M;
_N = m._N;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = m._data[i];
}
}
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row);
int columns = (end_coloumn - start_coloumn);
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
Matrix Matrix::operator+(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] + other._data[x];
}
return temp;
}
Matrix Matrix::operator*(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] * other._data[x];
}
return temp;
}
Matrix Matrix::operator-(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] - other._data[x];
}
return temp;
}
void Matrix::replace_Block(Matrix& noisy, Matrix& shuffled,int k, int j, int i)
{
int val_to_replace = 0;
for (int i = 0; i < 3 * 3; i++)
{
val_to_replace = shuffled.get(i, j);
noisy.set(i, j, val_to_replace);
}
}
void Matrix::set_Block(Matrix block, Matrix& Noisy, int start_row, int end_row)
{
int ctr = 0;
int ctr2 = 0;
int ctr3 = 0;
for (int i = 0; i < 3; i++)
{
Noisy._data[(start_row*_M)+i+4] = block.get(i, ctr);
ctr++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 3] = block.get(j, ctr2);
ctr2++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 2] = block.get(j, ctr3);
ctr3++;
}
}
double Matrix::get_Sum(Matrix m)
{
double total = 0;
short row = m.get_M();
short column = m.get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m.get(j,i);
}
}
return total;
}
double Matrix::get_Sum(Matrix* m)
{
double total = 0;
short row = m->get_M();
short column = m->get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m->get(i, j);
}
}
return total;
}
double Matrix::get(int i, int j)
{
return _data[(i * _M) + j];
}
void Matrix::write_Block(int i, int j)
{
for (int ctr = 0; ctr < i; ctr++)
{
for (int ctr2 = 0; ctr2 < j; ctr2++)
{
std::cout << " " << this->get(ctr,ctr2);
}
std::cout << std::endl;
}
}
void Matrix::set(int i, int j, double val)
{
this->_data[(i*_M) + j] = val;
}
void Matrix::set_N(int N)
{
_N = N;
}
void Matrix::set_M(int M)
{
_M = M;
}
int Matrix::get_N()
{
return _N;
}
int Matrix::get_M()
{
return _M;
}
Matrix::~Matrix()
{
"Matrix::~Matrix() is invoked";
delete[] _data;
}
If it would be helpful to see main() I can supply that too, however all it really contains is the creation of the matrix objects using overloaded constructors.
explanation
Answer is only 4 years late . . .
Anyway. Maybe it will help somebody else. The secret is to use a std::valarray. With that it is utmost simple to work on a matrix. And, many many functions are available.
All the functions that you want to implement are already available.
And you sub-matrix coy can be a one liner . . .
Please see example code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include <iomanip>
constexpr size_t NRows = 6;
constexpr size_t NCols = 8;
constexpr size_t SubNRows = 2;
constexpr size_t SubNCols = 3;
void debugPrint(std::valarray<int> &v, size_t nrows = NRows, size_t ncols = NCols)
{
for (int r = 0; r < nrows; ++r) {
for (int c = 0; c < ncols; ++c)
std::cout << std::setw(3) << v[r*ncols+c] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main()
{
std::valarray<int> v1(NRows * NCols); // Define array with given size
std::iota(std::begin(v1),std::end(v1),0); // Fill the array with consecutive nunbers
debugPrint (v1); // Print the result
std::cout << "\nSum = " << v1.sum() << "\n\n"; // Print the sum of all values in matrix
std::valarray<int> v2(v1); // Create a 2nd matrix as a copy to the first
v2 += 100; // Add 100 to each value in the matrix
debugPrint(v2);
std::valarray<int> v3(NCols); // Get one column
v3 = v1[std::slice(2,NRows,NCols)];
debugPrint(v3,NRows,1);
std::valarray<int> subV2(SubNRows*SubNCols); // So, now the sub array
subV2 = v2[std::gslice(12,{SubNRows, SubNCols},{NCols,1})]; // Slice it out
debugPrint(subV2, SubNRows, SubNCols);
v1[std::gslice(25,{SubNRows, SubNCols},{NCols,1})] = subV2; // And copy to the first array
debugPrint (v1);
return 0;
}