I have template class Matrix and I want to create container to it without stl, but i have a problem with addding matrices to container (same matrices!!!). I create temp container that gets all the data and then delete all my data from container. I create new space for +1 Matrix in container and then try to put everything to my new container:
template<int row, int col, typename T=int>
class MatrixContainer {
public:
MatrixContainer<row, col, T>() {
size = 0;
container = new Matrix<row,col,T>[size];
}
void addMatrix(const Matrix<row, col, T> &mat) {
this->size=this->size+1;
Matrix<row,col,T> *temp = new Matrix<row,col,T>[this->size-1];
for (int i = 0; i < size-1; ++i) {
temp[i] = this->container[i];
}
delete[] this->container;
this->container = new Matrix<row,col,T>[size];
for (int i = 0; i < size-1; ++i) {
this->container[i] = temp[i];
}
container[size]=mat;
delete[]temp;
}
private:
Matrix<row, col, T> *container;
int size;
};
Everything compiles but when it sees
container[size]=mat;
it calls to copy constructor and then fails. That's a copy constructor in template class Matrix:
Matrix(const Matrix &other) {
this->elements = new T *[other.rows];
for (int i = 0; i < other.rows; i++) {
this->elements[i] = new T[other.cols];
}
this->rows = other.rows;
this->cols = other.cols;
for (int i = 0; i < this->rows; ++i) {
for (int j = 0; j < this->cols; ++j) {
this->elements[i][j] = other.elements[i][j];
}
}
}
I already tried everything but it fails every time when it gets this line
Related
I am trying to write a matrix class for linear algebra calculations. I have almost finished writing what I wanted. but I have a little trouble in creating a constructor that uses list initialization to create a matrix.
this is my class data members:
template <typename T>
class Matx
{
private:
// data members
//rows and columns of matrix
int rows, cols;
//pointer to pointer to type T
T** matrix;
and this is my code for initialization:
template <typename T>
Matx<T>::Matx(T* ptM[], int m, int n) : rows(m), cols(n)
{
matrix = new T*[rows];
for (int i = 0; i < rows; i++)
matrix[i] = new T[cols];
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
matrix[i][j] = *(ptM[i] + j);
}
in main:
double mat[][5] = { {5,5,-1,7,54},{4,-9,20,12,-6},{9,-18,-3,1,21},{ 61,-8,-10,3,13 },{ 29,-28,-1,4,14 } };
double* pm[5];
for (int i=0;i<5;i++)
pm[i]=mat[i];
Matx<double> yourMat = Matx<double>(pm, 5,5);
but I think there is a better way to do it.
what I want is to be able to initialize it like arrays. something like this:
Matx<double> yourMat = { {5,5,-1,7,54},{4,-9,20,12,-6},{9,-18,-3,1,21},{ 61,-8,-10,3,13 },{ 29,-28,-1,4,14 } };
Is it possible?
It is definitely possible, I have made constructors that use initializer lists for similar classes. A constructor like this should do the job:
template <typename T>
Matx<T>::Matx(std::initializer_list<std::initializer_list<T>> listlist) {
rows = (int)(listlist.begin())->size();
cols = (int)listlist.size();
matrix = new T*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new T[cols];
for (int j = 0; j < cols; j++) {
matrix[i][j] = ((listlist.begin()+i)->begin())[j];
}
}
}
For anyone with similar issue, this version has some minor corrections to the other answer. Tried this and it works in gcc 7.3, ubuntu 16.04.
template <typename T>
Matx<T>::Matx(std::initializer_list<std::initializer_list<T>> listlist) {
rows = (int)(listlist.begin())->size(); /* pointer correction here */
cols = (int)listlist.size();
matrix = new T*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new T[cols];
for (int j = 0; j < cols; j++) {
matrix[i][j] = ((listlist.begin()+i)->begin())[j]; /* again minor correction */
}
}
}
i need some help. This is my first that hugh program in c++ (pointers are nightmare). I tried everything and i can't find what i did wrong.
class aghMatrix {
private:
T ** matrix;
int n;
int m;
public:
aghMatrix() : n(0), m(0) {};
aghMatrix(int _n, int _m);
aghMatrix(const aghMatrix& other);
~aghMatrix();
void setItem(int n, int m, T item);
void setItems (T * wsk);
void setItems(int r, int c ...);
void setAll();
void getALL();
bool couldbeadded(char * word, char sign);
bool equals (T first, T second);
T operator()(int a, int b);
aghMatrix<T> & operator+(const aghMatrix<T> & other);
aghMatrix<T> & operator*(const aghMatrix<T> & other);
aghMatrix<T> & operator= ( const aghMatrix<T> & other);
bool operator== (const aghMatrix<T> & other);
bool operator!= (const aghMatrix<T> & other);
};
Test :
char* cpt[] = {"to", "jest", "tablica", "wyrazow", "o", "rozmiarze", "jedenascie", "ktore", "beda", "elementami", "macierzy"};
aghMatrix<char*> cpm3(3, 1);
aghMatrix<char*> cpm4;
cpm3.setItems(cpt+3);
cpm4 = cpm3; // here my consol stop responding.
Constructors :
//default
aghMatrix() : n(0), m(0) {};
//with param
template <class T>
aghMatrix<T>::aghMatrix(int _n, int _m)
{
n = _n;
m = _m;
matrix = new T * [n];
for (int i = 0; i < n; i ++)
{
matrix[i] = new T[m];
}
}
setitems:
template <class T>
void aghMatrix<T>::setItems (T * wsk)
{
int licznik = 0;
for(int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
matrix[i][j] = wsk[licznik];
licznik ++;
}
}
}
Operator= for char*
template <>
aghMatrix<char*> & aghMatrix<char*>::operator= ( const aghMatrix<char*> & other)
{
if ( & other != this)
{
if ( (other.n == n) && (other.m == m) && (this->matrix != 0))
{
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
for(int ii = 0; ii < strlen(other.matrix[i][j]); ii++)
{
matrix[i][j][ii] = other.matrix[i][j][ii];
}
}
}
}
else
{
if(this->matrix)
{
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
delete [] matrix[i][j];
}
delete [] matrix[i];
}
delete [] matrix;
n = 0;
m = 0;
matrix = NULL;
}
n = other.n;
m = other.m;
matrix = new char **[n];
for(int i = 0; i < n; i ++)
{
matrix[i] = new char*[m];
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
matrix[i][j] = new char[strlen(other.matrix[i][j])];
for(int ii = 0; ii < strlen(other.matrix[i][j]); ii ++)
{
matrix[i][j][ii] = other.matrix[i][j][ii];;
}
}
}
}
}
return *this;
}
I tried everything and still i'm getting this problem with console (it looks like i'm using somewhere uninitialized memory or sth). I cant solve this problem alone is alone can anybody help me?
EIDT: One more thing : The error shows when the program comes to end and after i change destructor :
Now looks like this :
template
aghMatrix<T>::~aghMatrix()
{
if (matrix)
{
for (int i = 0; i < n; i ++)
{
delete [] matrix[i];
}
delete [] matrix;
matrix = NULL;;
n = 0;
m = 0;
}
}
the previous version of destructor :
template <class T>
aghMatrix<T>::~aghMatrix()
{
if (matrix =! 0)
{
for (int i = 0; i < n; i ++)
{
delete [] matrix[i];
}
delete [] matrix;
matrix = 0;
}
}
maybe here is the reason of error?
EDIT:---------------------
I found the reason of my error here it is:
when i create
aghMatrix<char*> cpm3(3, 1);
cpm4 = cpm3; //destructor create a problem
but when i do something like this:
aghMatrix<char*>cpm3(3,2); //or somekind of other number than '1'
cpm4 = cpm3; // everything works fine
any ideas?
I got a class for boolean matrix.
Deallocating memory in destructor does not work correctly, it tries to delete invalid pointers - as I noticed, that happens when I try to multiply.
In operator* I return local object as a result and that part causes invalid pointers - so program crashes when deleting in destructor - the question is why that happens on this code ? and how to return result properly ?
Here's the code:
#include <iostream>
using namespace std;
class BoolMatrix
{
private:
bool ** items;
public:
size_t rows, cols;
BoolMatrix(size_t = 0, size_t = 0);
~BoolMatrix();
BoolMatrix operator * (const BoolMatrix &) const;
//some other members
};
BoolMatrix::BoolMatrix(size_t r, size_t c) : rows(r), cols(c)
{
items = new bool*[r];
for (size_t i = 0; i < r; i++)
{
items[i] = new bool[c];
for (size_t j = 0; j < c; j++)
items[i][j] = 0;
}
}
BoolMatrix::~BoolMatrix()
{
if (items)
{
for (size_t i = 0; i < rows; i++)
{
if (items[i])
delete[] items[i];
items[i] = NULL;
}
delete[] items;
items = NULL;
}
}
BoolMatrix BoolMatrix::operator * (const BoolMatrix& that) const
{
//NxM * MxK = NxK
if (cols != that.rows)
return NULL;
Matrix res(rows, that.cols);
for (size_t i = 0; i < rows; i++)
{
for (size_t j = 0; j < that.cols; j++)
for (size_t l = 0; l < that.rows; l++)
res.items[i][j] = (res.items[i][j] + items[i][l]*that.items[l][j]) != 0;
}
return res;
}
int main(int argc, char *argv[])
{
size_t n;
cin >> n;
BoolMatrix a(n, n);
//matrix reading code
a*a;
return 0;
}
Thanks
I think that what happens is that you are trying to delete[] memory on the stack.
Instead of
Matrix res(rows, that.cols);
try with
Matrix res=new Matrix(rows, that.cols);
overload the copy constructor to copy whole array, so when function deletes it's local instance of class, it will delete it's own matrix, while function in main will have it's copy of matrix (note that if you leave it like this, what u get as result of function and variable from main which you equal in main to the result of function, point to exact same memory, that's why u need copy constructor)
overload '=' operator and use it like a=a*a ; and destructor must be
BoolMatrix::~BoolMatrix()
{
for (size_t i = 0; i < rows; i++)
{
delete [] items[i];
}
delete[] items;
}
}
I'm trying to overload the + operator for a project that I'm doing but this keeps on happening. I think the reason is that the object I created is getting deleted when the operator is getting invoked. Not sure how to fix it though. Here's part of my code:
Matrix Matrix::operator+ (const Matrix& m) const
{
//something wrong here
Matrix sum(rows, cols);
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
sum.element[i][j] = this->element[i][j] + m.element[i][j];
}
}
return sum;
}
Additional Information
Matrix::Matrix(int r, int c)
{
rows = r;
cols = c;
element = new int *[c];
for (int i = 0; i < c; i++)
{
element[i] = new int[r];
}
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
element[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& m)
{
this->element = m.element;
}
Matrix::~Matrix()
{
//freeing up the arrays
for (int i = 0; i < cols; i++)
{
delete[] element[i];
element[i] = NULL;
}
delete[] element;
element = NULL;
}
Matrix& Matrix::operator= (const Matrix& m)
{
//problem if rows and cols are longer in the new matrix
//need to create a temp matrix to expand to new one
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
this->element[i][j] = m.element[i][j];
}
}
return *this;
}
int* Matrix::operator[] (int n)
{
return element[n];
}
The specific error I am getting is:
Debug Assertion Failed!
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
In line 52 which I did this:
Matrix total = mat + m;
Where mat and m are both object matrices
I'm guessing the problem is caused by this:
Matrix::Matrix(const Matrix& m)
{
this->element = m.element;
}
That is an invalid copy constructor for two reasons. First, you're not initializing rows or cols. Second, you'll now have two Matrix objects pointing to the same memory - both of which will delete it on destruction:
{
Matrix m1(3, 5);
Matrix m2 = m1;
} // BOOM!
You need to do a deep copy here:
Matrix::Matrix(const Matrix& m)
: rows(m.rows), cols(m.cols)
{
element = new int *[cols];
for (int i = 0; i < cols; ++i) {
element[i] = new int[rows];
for (int j = 0; j < rows; ++j) {
element[i][j] = m.element[i][j];
}
}
}
I've been tasked with creating a class for a two dimensional dynamic array and I am stuck at a part where I need to create a member function which I can call upon to change a specific position in the 2D array to a value of my choosing.
class TwoD
{
public:
void setRowCol(int numRow, int numCol, double value);
TwoD();
TwoD(int row, int col);
void fillArray();
void outputArray();
private:
double** dArray = new double* [MaxRow];
int MaxRow;
int MaxCol;
};
TwoD::TwoD()
{
MaxCol = 3;
MaxRow = 3;
for (int i = 0; i < 3; i++)
{
dArray[i] = new double[3];
}
}
void TwoD::setRowCol(int numRow, int numCol, double value)
{
dArray[numRow][numCol] = value;
}
So the part I am having trouble with is the last part with the function setRowCol. I think that the problem is that it's not passing a 'deep' copy of the array but rather the original array itself.
Make the MaxRow as static variable & initialize it to appropriate value(3) before using it to create dArray.
Without std::vector, and using double**, you may have something like:
class TwoD
{
public:
TwoD(int row, int col) : maxRow(row), maxCol(col) {
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol] {};
}
}
~TwoD() {
Delete();
}
TwoD(const TwoD& rhs) : maxRow(rhs.maxRow), maxCol(rhs.maxCol) {
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol];
for (int j = 0; j != maxCol; ++j) {
dArray[i][j] = rhs.dArray[i][j];
}
}
}
TwoD& operator = (const TwoD& rhs) {
if (&rhs == this) {
return *this;
}
Delete();
maxRow = rhs.maxRow;
maxCol = rhs.maxCol;
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol];
for (int j = 0; j != maxCol; ++j) {
dArray[i][j] = rhs.dArray[i][j];
}
}
}
void setRowCol(int numRow, int numCol, double value) {
dArray[numRow][numCol] = value;
}
private:
void Delete() {
for (int i = 0; i != maxRow; ++i) {
delete [] dArray[i];
}
delete [] dArray;
}
private:
double** dArray;
int maxRow;
int maxCol;
};