Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.11.2011, 20:57   #1
Jugger
Пользователь
 
Регистрация: 30.01.2008
Сообщений: 99
По умолчанию Ошибка после исполнения методов класса

В этом коде

Код:
#include "stdafx.h"

#include "iostream"
#include "ctime"

using namespace std;

class matrix{
public:
	matrix() : a(0) {}; // Initialize a = NULL
	matrix(int);
	matrix(int, int);
	~matrix();
	matrix plus(matrix&,matrix&);
	matrix minus(matrix&,matrix&);
	matrix umn1(matrix&,int);
	matrix umn2(matrix&,matrix&);
	void printErr();
	
	double val(int,int);
	void putx(int,int, double);
	void out();
	void random_matrix();
    int N();
	int M();
	
	

	
	
private:
    double * a;
	int n,m,e;

};

matrix::matrix(int y){
		if(y<=0)
			e=1;
		else{
		a=new double[y*y];
		n=y;
		m=n;
		}
	}
matrix::matrix(int r, int u){
		if(r<=0||u<=0)
			e=1;
		else{
		a=new double[r*u]; // r lines and u columns
		
		n=r;
		m=u;
		}
	}
matrix::~matrix(){
		if(a)
			delete [] a;
	} 
matrix matrix::plus(matrix &a,matrix &b){
	matrix w(a.N(),a.M());
	if(a.n!=b.n||a.m!=b.m) e=5;
	else
	
	for(int i=0;i<a.N();i++)
		for(int j=0;j<a.M();j++)
			w.putx(i,j,a.val(i,j)+b.val(i,j));
	
	
     return w;
}

matrix matrix::minus(matrix &a,matrix &b){
	matrix w(a.N(),a.M());
	if(a.n!=b.n||a.m!=b.m) e=5;
	else
	
	for(int i=0;i<a.N();i++)
		for(int j=0;j<a.M();j++)
			w.putx(i,j,a.val(i,j)-b.val(i,j));

	return w;
	
	
}

matrix matrix::umn1(matrix &a,int y){
	matrix w(a.N(),a.M());
	if(!a.n) e=3;
	else

	
	for(int i=0;i<a.N();i++)
		for(int j=0;j<a.M();j++)
			w.putx(i,j,a.val(i,j)*y);
	return w;
	
}

matrix matrix ::umn2(matrix &a,matrix &b){
matrix w(a.N(),a.M());
if(a.n!=b.m) e=7;
else{
double sum;
	
	
	for(int i=0;i<a.N();i++)
		for(int j=0;j<b.N();j++){
		         sum=0;
				 for(int k=0; k<a.N(); k++)
					       sum+=a.val(i,k)*b.val(k,j);
				  w.putx(i,j,sum);
				 }
				
}
			
	
	return w;
}


double matrix:: val(int i,int j){
		if(i>n||j>m)
			e=4;
		else
		return a[i*m + j];
	}
	void matrix:: putx(int i,int j, double r){
		if(i>n||j>m)
			e=4;
		else
		a[i*m + j]=r;
	}
	void matrix::out(){
		if(!a)
			e=3;
		else{
		for(int i=0;i<n;i++){
			cout << endl;
			for(int j=0;j<m;j++)
				cout << val(i,j) << " ";
		}
		cout << endl;
		}
	}
	void matrix:: random_matrix(){
		srand((unsigned)time(0)); // srand out of the cycle
		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++)
				putx(i, j, rand());
	}

	void matrix::printErr(){

	if (e==0)
		cout<<"OK. No errors."<<endl;
	else if (e==1)
		cout<<"Negative or null matrix size!"<<endl;
	else if(e==2)
		cout<<"Incompatible sizes!"<<endl;
	else if(e==3)
		cout<<"The matrix doesn't exist!"<<endl;
	else if(e==4)
		cout<<"Index out of boundaries!"<<endl;
	else if(e==5)
		cout<<"Different matrix sizes! Addition or subtraction forbidden!"<<endl;
	else if(e==7)
		cout<<"Incompatible sizes, matrix-to-matrix multiplication not allowed!"<<endl;
}


	int matrix::N(){
		return n;
	}

	int matrix::M(){
		return m;
	}


int main()
{
	matrix a(10);
	matrix b(10);
	matrix c(10);
	a.random_matrix();
	b.random_matrix();
	c=c.plus(a,b);
	c.out();
	c=c.minus(a,b);
	c.out();
	c=c.umn1(a,15);
	c.out();
	c=c.umn2(a,b);
	c.out();
	c.printErr();
	
	system("pause");
    

    return 0;
}
При запуске программы появляется следующее


Расставив точки останова выяснил что эта штука появляется при работе методов plus, minus, umn1 и umn2 после возвращения ими значения но до запуска из мэйна следующего метода

В чем может быть дело ?
Jugger вне форума Ответить с цитированием
Старый 07.11.2011, 11:22   #2
Abstraction
Старожил
 
Аватар для Abstraction
 
Регистрация: 25.10.2011
Сообщений: 3,178
По умолчанию

Возьмём plus.
В методе создаётся локальная переменная w (вызван new для её массива).
Мы с ней работаем, и в конце говорим return w; - при типе возвращаемого значения matrix.
Это значит, что w должна копироваться в возвращаемый объект, вызывается matrix::matrix(const matrix& cpy).
После чего для w вызывается деструктор, в котором мы говорим delete.

Как можно заметить, класс не содержит конструктора копирования matrix::matrix(const matrix& cpy). В этом случае, компилятор генерирует его самостоятельно и самым простым образом: побитово копируя значения полей класса. К сожалению, в данном случае это означает, что копия получает то же самое значение указателя a, для которого мы на выходе из функции вызвали delete.
Всё вышеуказанное относится и к работе оператора присваивания, const matrix& matrix::operator=(const matrix& cpy).

Последний раз редактировалось Abstraction; 07.11.2011 в 11:23. Причина: смайлики, чтоб их...
Abstraction вне форума Ответить с цитированием
Старый 08.11.2011, 22:17   #3
Jugger
Пользователь
 
Регистрация: 30.01.2008
Сообщений: 99
По умолчанию

То есть мне надо объявить конструктор копирования, и с помощью него инициализировать возвращаемый методом объект ? А деструктор не уничтожит и этот возвращаемый объект после завершения работы метода ?

И где это следует делать, в самом методе перед возвращением объекта ?

Вот так будет корректно ?

Код:
matrix::matrix(const matrix& cpy)
	:n(n),m(m),e(e),a(new double[sizeof(double)]) {}
А оператор присваивания следует переопределить ?

Последний раз редактировалось Jugger; 08.11.2011 в 22:20.
Jugger вне форума Ответить с цитированием
Старый 08.11.2011, 23:04   #4
Jugger
Пользователь
 
Регистрация: 30.01.2008
Сообщений: 99
По умолчанию

Сделал вот что
Код:
matrix::matrix(const matrix& cpy){
	n=cpy.n;
	m=cpy.m;
	a=cpy.a;
}
Код:
matrix matrix::plus(matrix &a,matrix &b){
	matrix w(a.N(),a.M());
	if(a.n!=b.n||a.m!=b.m) e=5;
	else
	
	for(int i=0;i<a.N();i++)
		for(int j=0;j<a.M();j++)
			w.putx(i,j,a.val(i,j)+b.val(i,j));
	
	matrix u(w);
     return u;
}
Абсолютно та же табличка
Jugger вне форума Ответить с цитированием
Старый 09.11.2011, 03:13   #5
An1ka
C++,DirectX/OpenGL
Форумчанин
 
Регистрация: 09.01.2011
Сообщений: 422
По умолчанию

Цитата:
Сообщение от Jugger Посмотреть сообщение
Сделал вот что
Код:
matrix::matrix(const matrix& cpy){
	n=cpy.n;
	m=cpy.m;
	a=cpy.a;
}
Надо не присваивать старые адреса новым указателям, а создавать новый объект, потому что предыдущий объект будет уничтожен деструктором и новые указатели будут указывать "в никуда".
Код:
matrix::matrix(const matrix& cpy){
   n=cpy.n;
   m=cpy.m;
   a=new double[n*m];
   memcpy( a, cpy.a, sizeof(double)*n*m);
}
An1ka вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка в использовании методов класса Jugger Общие вопросы C/C++ 2 26.10.2011 01:29
Описание методов вне класса Jugger Общие вопросы C/C++ 5 17.10.2011 20:19
Вектор из callback'ов методов класса Gongled Общие вопросы C/C++ 7 05.01.2011 16:29
массив методов класса DartDayring Общие вопросы C/C++ 0 07.12.2010 20:00
Использование методов вне класса prikolist Общие вопросы C/C++ 12 07.05.2009 13:57