本菜写了一个小程序
能够创建一个矩阵,规定长宽,并进行矩阵之间的加减运算
代码如下
#include<iostream>
using namespace std;
class matrix //创建矩阵类
{
private:
int lines;
int rows;
int **num; //建立二重数组
public:
matrix(int a,int b) //构造函数
{
lines=a;
rows=b;
cout<<"矩阵初始化"<<endl;
num=new int*[lines];
int x,y;
for(y=0;y<lines;y++)
{
num[y]=new int[rows]; //循环完成new申请内存
}
}
/*matrix(matrix& father) //拷贝构造函数
{
cout<<"调用拷贝构造函数"<<endl;
lines=father.lines;
rows=father.rows;
int x,y;
for(y=0;y<lines;y++)
{
for(x=0;x<rows;x++)
{
num[x][y]=father.num[x][y]; //循环读入矩阵元素
}
}
}*/
void in(); //输入函数
void out(); //输出函数
int get_num(int x,int y) //取用指定元素的函数(内联)
{
return num[x][y];
}
void operate(int mode,matrix m1,matrix m2); //运算函数,包含加和减
~matrix() //析构函数 释放矩阵空间
{
}
void matrix_free(); //释放矩阵空间函数
};
void matrix::matrix_free()
{
int i;
for(i=0;i<lines;i++)
{
delete []num[i];
}
delete []num;
}
void matrix::in()
{
cout<<"请按顺序输入矩阵元素:"<<endl;
int x,y;
for(y=0;y<lines;y++)
{
for(x=0;x<rows;x++)
{
cin>>num[x][y]; //循环输入矩阵元素
}
}
}
void matrix::out() //此函数可以按格式输出矩阵
{
int x,y;
for(y=0;y<lines;y++)
{
for(x=0;x<rows;x++)
{
cout<<num[x][y];
if(x!=rows-1)
{
cout<<" ";
}
}
cout<<endl;
}
}
void matrix::operate(int mode,matrix m1,matrix m2) //运算函数,mode=1代表加,mode=-1代表减,m1,m2为待处理矩阵
{
int x,y;
for(y=0;y<lines;y++)
{
for(x=0;x<rows;x++)
{
num[x][y]=m1.get_num(x,y)+mode*m2.get_num(x,y); //运算部分
}
}
}
int main(void)
{
int a=0,b=0;
cout<<"输入矩阵大小(行 列):"<<endl;
while(a<=0||b<=0)
{
cin>>a>>b;
if(a<=0||b<=0)
{
cout<<"输入错误,重新输入:"<<endl;
}
}
matrix A1(a,b),A2(a,b),A3(a,b); //创建三个矩阵
A1.in(); //输入初始化
A2.in();
A3.operate(1,A1,A2); //A3=A1+A2
cout<<"矩阵和:"<<endl;
A3.out(); //输出
A3.operate(-1,A1,A2); //A3=A1-A2
cout<<"矩阵差:"<<endl;
A3.out(); //输出
A1.matrix_free(); //释放矩阵空间
A2.matrix_free();
A3.matrix_free();
}
此程序目前问题有三个
1.拷贝构造函数出错,只能注释掉,否则输入完两个矩阵后回车程序未响应
2.释放矩阵空间的不能写在析构函数里,否则输出结果不正确(A3=A1-A2的最后一行)
3.输入矩阵的列不能大于行,否则输入完第一行数字并回车后程序未响应
请前辈指导,谢谢
第一个问题,num没有分配空间就进行赋值,导致出错。类对象作为方法的参数时,是按照“传值”的方式传递的,也就是说,会复制一个副本,这时会调用拷贝构造函数(void matrix::operate(int mode,matrix m1,matrix m2) 这里的m1、m2是A1、A2的副本而不是指针)。因为副本m1、m2没有经过构造函数初始化,所以副本中的num是没有分配空间的,而你再拷贝构造函数中引用num,所以会出错。修改:在拷贝构造函数中先检查nun指针是否为null,如果是,则在拷贝构造函数中为num分配空间。
第二个问题,析构函数在类对象的生命周期结束的时候或者被delete掉的时候才会被调用,所以,在析构函数中释放动态分配的内存是完全可以的。问题不在于你在析构函数中释放内存,而在于以“传值”的方式传递类参数。上面说过,参数m1\m2是A1\A2的副本,这个副本的生命周期在方法调用结束之后就完了,所以第一次使用A3.operate(1,A1,A2)结束时会调用析构函数,来清理m1\m2。按理说,m1\m2是A1\A2的副本,清理m1\m2并不会影响A1\A2,问题蹊跷的地方在于,m1\m2和A1\A2之间共享了一块内存,这个内存就是num所指向的空间。为什么会这样
?因为m1=A1,m2=A2时,意味着m1.num=A1.num,m2.num=A2.num。如果num是一个非指针类变量,那么m1.num就是A1.num的副本,现在的情况是,num是指针,指针之间的赋值,意味着大家都指向同一块内存。在你释放掉m1.num指向的内存就是释放A1.num指向的内存。修改:不在析构函数中释放内存,或者方法中的参数传递改为“传址”,如void matrix::operate(int mode,matrix& m1,matrix& m2)。
第三个问题,其实就是数组元素访问出现越界。修改,in/out方法中的,for循环,外层循环应该是矩阵的行,用x作下标。内循环应该是矩阵的列用y做下标。而你刚好相反了。
最后,对矩阵的运算其实可以运用运算符的重载,这样要方便的多。对于拷贝构造函数,除非你知道你要干什么,否则慎用。在你这段程序中,我没看到使用拷贝构造函数的必要。
这是修改后的代码
#include<iostream>
using namespace std;
class matrix //创建矩阵类
{
private:
int lines;
int rows;
int **num; //建立二重数组
public:
matrix(int a, int b) //构造函数
{
lines = a;
rows = b;
cout << "矩阵初始化" << endl;
num = new int*[lines];
int x, y;
for (y = 0;y<lines;y++)
{
num[y] = new int[rows]; //循环完成new申请内存
}
}
matrix(matrix& father) //拷贝构造函数
{
cout<<"调用拷贝构造函数"<<endl;
lines=father.lines;
rows=father.rows;
////////////////////////////////////////////修改后
if (father.num == NULL)
{
father.num = new int*[lines];
for (int y = 0;y < lines;y++)
{
num[y] = new int[rows];
}//循环完成new申请内存
}
////////////////////////////////////////////
int x,y;
for(y=0;y<lines;y++)
{
for(x=0;x<rows;x++)
{
num[x][y]=father.num[x][y]; //循环读入矩阵元素
}
}
}
void in(); //输入函数
void out(); //输出函数
int get_num(int x, int y) //取用指定元素的函数(内联)
{
return num[x][y];
}
void operate(int mode, matrix& m1, matrix& m2); //运算函数,包含加和减
~matrix() //析构函数 释放矩阵空间
{
int i;
for (i = 0;i<lines;i++)
{
delete[]num[i];
}
delete[]num;
}
//void matrix_free(); //释放矩阵空间函数
};
/*void matrix::matrix_free()
{
int i;
for (i = 0;i<lines;i++)
{
delete[]num[i];
}
delete[]num;
}*/
void matrix::in()
{
cout << "请按顺序输入矩阵元素:" << endl;
int x, y;
for (x = 0;x<lines;x++)
{
for (y = 0;y<rows;y++)
{
cin >> num[x][y]; //循环输入矩阵元素
}
}
}
void matrix::out() //此函数可以按格式输出矩阵
{
int x, y;
for (x = 0;x<lines;x++)
{
for (y = 0;y<rows;y++)
{
cout << num[x][y];
if (y != rows - 1)
{
cout << " ";
}
}
cout << endl;
}
}
void matrix::operate(int mode, matrix& m1, matrix& m2) //运算函数,mode=1代表加,mode=-1代表减,m1,m2为待处理矩阵
{
int x, y;
for (x = 0;x<lines;x++)
{
for (y = 0;y<rows;y++)
{
num[x][y] = m1.get_num(x, y) + mode*m2.get_num(x, y); //运算部分
}
}
}
int main(void)
{
int a = 0, b = 0;
cout << "输入矩阵大小(行 列):" << endl;
while (a <= 0 || b <= 0)
{
cin >> a >> b;
if (a <= 0 || b <= 0)
{
cout << "输入错误,重新输入:" << endl;
}
}
matrix A1(a, b), A2(a, b), A3(a, b); //创建三个矩阵
A1.in(); //输入初始化
A2.in();
A3.operate(1, A1, A2); //A3=A1+A2
cout << "矩阵和:" << endl;
A3.out(); //输出
A3.operate(-1, A1, A2); //A3=A1-A2
cout << "矩阵差:" << endl;
A3.out(); //输出
//A1.matrix_free(); //释放矩阵空间
//A2.matrix_free();
//A3.matrix_free();
}