Destruktor po wywołaniu funkcji.

0

Witam,
Piszę sobie mały program operujący na macierzach... i zasadniczo mam problem tego typu że jak przeciążam operator "+" to program uruchamia destruktor kilka razy i to jakiś losowych obiektów, gdyż je numerowałem i sprawdzałem co jest nie tak.

Mam klasę zdefiniowaną w pliku nagłówkowym następująco.

class Matrix 
{
	private:
		
		double** elements;
		int rows;
		int cols;
		double** Resize(double ** elements, int new_rows, int new_cols);

	public:
		Matrix(int rows, int cols);  // Konstruktor
		~Matrix();					 // Dekonstruktor
		
		void EnterData();
		void ShowData();
		int LU(Matrix* L, Matrix* U, int mode=0);  // not all matrix

		Matrix operator+ (Matrix B);
		
		double Determinant();
		double Rank();
		Matrix* Transpose();
		void    Transpose(bool);
		Matrix* Inversion();
		
	protected:
		int z;
}; 

Funkcje

Matrix::Matrix(int rows, int cols)
{
			this->rows = rows;
			this->cols = cols;
			elements = new double* [rows];
			for(int i=0;i<rows;i++)
			{
				elements[i]=new double[cols];
				for(int j=0;j<cols;j++)
					elements[i][j]=0;
			}
}

Matrix::~Matrix()
{
			if(elements==NULL) return;

			for(int i=0;i<rows;i++)
			{
				for(int j=0;j<cols;j++)
					elements[i][j]=NULL;
				delete[] elements[i];
			}
			delete[] elements;
			elements = NULL;
			rows=0;
			cols=0;
}

Matrix Matrix::operator + (Matrix B)
{
	Matrix Wynik_dodawania(this->rows,this->cols);

	for( int i=0; i<this->rows; i++ ) 
	{
		for( int j=0; j<this->cols; j++ ) 
		{
			Wynik_dodawania.elements[i][j] = this->elements[i][j] + B.elements[i][j];
		}
	}
	return Wynik_dodawania;
} 
void Matrix::EnterData()  // dodac walidacje danych wprowadzanych
{
	for(int i=0;i<rows;i++)
		for(int j=0;j<cols;j++)
		{
			std::cout<<"Podaj wartosc w wierszu "<<i<<" kolumnie "<<j<<" "; 
			std::cin>>elements[i][j];
		}

	system("cls");

}

void Matrix::ShowData()  // dodac walidacje danych wprowadzanych
{

	for(int i=0;i<rows;i++)
	{
		for(int j=0;j<cols;j++)
		{
			std::cout<<elements[i][j]<<" ";
		}
		std::cout<<std::endl;
	}

}

I w samej funkcji main mam coś takiego

int main()
{
	Matrix A(2,2);
	A.EnterData();
	A.ShowData();
	Matrix B(2,2);
	B= A+A;
	B.ShowData();
	return 0;
} 

tak jak wspomniałem program wykrzacza się po wykonaniu dodawania na destruktorze który wywołuje się trzy razy, jakaś porada dla mnie?

1

Masz przekazywanie przez wartość:
Matrix operator + (Matrix B)
zaś brak konstruktora kopiującego.

Masz użyte przepisanie:
B= A+A;
zaś brak przeciążenia operator=

1

A gdzie masz konstruktor kopiujący i operator przypisania? Teraz usuwasz sobie cały czas dane z macierzy, bo wskaźnik jest po prostu przepisywany (a to nie wskaźnik powinien być kopiowany, tylko dane, można też wykorzystać COW albo inne bajery). Poza tym operator + powinien i tak przyjmować stałą referencję.

Edit: ojej, spóźniłem się nieco.

0

Dzięki panowie za szybką odpowiedź :)

Teraz działa i zmiany wyglądają tak:

 
Matrix::Matrix(const Matrix &Copy) //Kopiujący
{
	rows = Copy.rows;
	cols = Copy.cols;
	elements = new double* [rows];
	for(int i=0;i<rows;i++)
	{
		elements[i]=new double[cols];
		for(int j=0;j<cols;j++)
			elements[i][j]=Copy.elements[i][j];
	}

}

Matrix Matrix::operator + (const Matrix &B)
{
	Matrix Wynik_dodawania(this->rows,this->cols);
	for( int i=0; i<this->rows; i++ ) 
	{
		for( int j=0; j<this->cols; j++ ) 
		{
			Wynik_dodawania.elements[i][j] = this->elements[i][j] + B.elements[i][j];
		}
	}
	return Wynik_dodawania;
}

Matrix& Matrix::operator= (const Matrix &A)
{
	for( int i=0; i<A.rows; i++ ) 
	{
		for( int j=0; j<A.cols; j++ ) 
		{
			this->elements[i][j] = A.elements[i][j];
		}
	}
	return  *this;
}

I czy wszytko jest tak jak powinno czy jeszcze inaczej powinno się pisać?

0

Ja bym dodał jeszcze move constructor.

0

Matrix Matrix::operator + (const Matrix &B)const ...

W Matrix& Matrix::operator= (const Matrix &A) - skąd założenie że A ma taki sam wymiar co this ? Brakuje resize

0

To const powinno być czy nie?

Resize jest, trochę naokoło zrobiony, ale jest.

Edit: Tylko że nie wkleiłem -.-

Matrix& Matrix::operator= (const Matrix &A)
{
	if(this->rows != A.rows || this->cols != A.cols)
	{
		elements = this->Resize(elements, A.rows , A.cols);
	}
	for( int i=0; i<A.rows; i++ ) 
	{
		for( int j=0; j<A.cols; j++ ) 
		{
			this->elements[i][j] = A.elements[i][j];
		}
	}
	return  *this;
} 
double** Matrix::Resize(double ** elements, int new_rows, int new_cols)
{
			for(int i=0;i<rows;i++)
			{
				for(int j=0;j<cols;j++)
					elements[i][j]=NULL;
				delete[] elements[i];
			}
			delete[] elements;
			double ** elements2;
			this->rows = new_rows;
			this->cols = new_cols;
			elements2 = new double* [rows];
			for(int i=0;i<rows;i++)
			{
				elements2[i]=new double[cols];
				for(int j=0;j<cols;j++)
					elements2[i][j]=0;
			}
			return elements2;
} 
0
Matrix& Matrix::operator= (const Matrix &A)

po pierwsze, trzeba na początku sprawdzić czy &A==this, jeżeli tak to od razu wyjść:

if (this==&A) return *this;

po drugie, jak już kol. _13th_Dragon wspomniał, trzeba zaalokować nową pamięć, jeśli rozmiar miałby się zmienić, albo this->elements jest NULL.

1 użytkowników online, w tym zalogowanych: 0, gości: 1