c ++分配和析构函数

时间:2014-12-05 16:02:31

标签: c++ destructor allocation

我上了这堂课:

int x;
int y;
int **mat;

MyMatrix::MyMatrix(int a, int b)
    :x(a), y(b)
{
    int i ,j;
    mat = new int*[x];
    for (int i = 0; i < x; ++i)
        mat[i] = new int[y];

    for (i = 0; i < x; ++i){
        for (j = 0; j < y; ++j){
            mat[i][j] = i + j;
        }
    }
}

MyMatrix& MyMatrix::add(MyMatrix m){
    int i, j;

    if (x != m.x || y != m.y) return *this;

    for (i = 0; i < x; ++i){
        for (j = 0; j < y; ++j){
            mat[i][j] += m.mat[i][j];
        }
    }

    return *this;
}

MyMatrix::~MyMatrix()
{
    for (int i = 0; i < x; ++i)
        delete[] mat[i];

    delete mat;
}

这是我的主要内容:

int main(){
    MyMatrix m(2, 3);
    MyMatrix m1(2, 3);

    m.add(m1);

    m.print();
}

一切正常,并给我打印正确的答案,但有一些分配问题。 我正在使用调试器,并且在第二次程序崩溃时看到该程序对析构函数进行了两次。

请解释我的问题是什么?为什么?

2 个答案:

答案 0 :(得分:2)

是的,当您调用m.add时,参数按值传递,因此在方法的条目处构建新矩阵,然后在结束时销毁。要消除此效果,请使用by-ref传递:

MyMatrix& MyMatrix::add(const MyMatrix &m){
...
}

这样原始的一个传递给函数,但const阻止你在方法执行期间修改它。

答案 1 :(得分:1)

我看到的最明显的事情是,在你的析构函数中,你需要在垫子上使用delete []。另一个问题是你需要提供一个拷贝构造函数。我相信this answer是最大的问题。当您传递值并复制MyMatrix时,默认的复制构造函数只会复制所有成员变量:xymat。这会生成mat 指针的副本,而不是它指向的数据。当该临时MyMatrix被销毁时,将删除m1中分配的数据,因为临时mat指向它。因此,当您的程序试图销毁m1时,它会删除一个已被删除的指针并导致崩溃。

复制构造函数如下所示:

MyMatrix::MyMatrix(const MyMatrix& other) : x(other.x), y(other.y)
{
    mat = new int*[x];
    for (int i = 0; i < x; ++i)
        mat[i] = new int[y];

    for (int i = 0; i < x; ++i){
        for (int j = 0; j < y; ++j){
            mat[i][j] = other.mat[i][j];
        }
    }
}

其他一些提示。您可能希望使用operator+=而不是add函数,以便编写如下代码:

m += m1;

只需将MyMatrix& MyMatrix::add(MyMatrix m)更改为MyMatrix& MyMatrix::operator+=(const MyMatrix &m)即可。此外,您的内存分配效率相对较低。它可以工作,但有更好的方法来实现2D矩阵。如果这是一个学习练习,这很好。如果您真的想在C ++中使用矩阵,我建议您查看像OpenCV这样的库。