2 deadpixels Deadpixels 于 2017.09.13 16:05 提问

帮忙看看这个程序出了什么问题

本菜写了一个小程序
能够创建一个矩阵,规定长宽,并进行矩阵之间的加减运算
代码如下

 #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.输入矩阵的列不能大于行,否则输入完第一行数字并回车后程序未响应

请前辈指导,谢谢

2个回答

qq_28249373
qq_28249373   2017.09.13 20:45
已采纳

第一个问题,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做下标。而你刚好相反了。
最后,对矩阵的运算其实可以运用运算符的重载,这样要方便的多。对于拷贝构造函数,除非你知道你要干什么,否则慎用。在你这段程序中,我没看到使用拷贝构造函数的必要。

Deadpixels
Deadpixels 万分感谢!!!
2 个月之前 回复
qq_28249373
qq_28249373   2017.09.13 20:56

这是修改后的代码

 #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();
}
Csdn user default icon
上传中...
上传图片
插入图片