多次*操作后调用析构函数时,重载*运算符失败

时间:2013-08-07 21:18:17

标签: c++ operator-overloading

我正在制作一个类来为我正在运行的测试做矩阵(和向量)数学并学习更多C ++。该课程如下:

class utlMatrix
{
private:
    int num_rows;
    int num_cols; // number of columns
    double **data; // array of pointers to the data

public:
    // default constructor, with initialization
    utlMatrix() : num_rows(0), num_cols(0), data(NULL) {};

    // constructor with size
    utlMatrix(int, int);

    // destructor
    ~utlMatrix();

    // copy constructor
    utlMatrix(const utlMatrix&);

    void copy(const utlMatrix &old); // copy 'old' to 'this'
    void zero(); // sets all values to zero
    void fill_rand(); //fills the data with random stuff
    void print(std::ostream&); // prints the matrix to a file

    // Operators
    utlMatrix& operator=(const utlMatrix&); // copies matrices
    friend utlMatrix operator+(const utlMatrix&, const utlMatrix&); // adds 2 matrices
    utlMatrix operator*(const utlMatrix&) const;

    //friend utlMatrix operator*(const utlMatrix&, const utlMatrix&); // multiplies 2 matrices
};

复制构造函数,赋值运算符和析构函数

// copy constructor
utlMatrix::utlMatrix(const utlMatrix &old) {
    copy(old);
}
utlMatrix& utlMatrix::operator=(const utlMatrix &old)    {
    copy(old);
    return *this;
}
void utlMatrix::copy(const utlMatrix &old)    {
    num_rows = old.num_rows;
    num_cols = old.num_cols;
    data = new float*[num_rows];
    for (int i = 0; i < num_cols; i++)
        data[i] = new float[num_cols];
    for (int i = 0; i < num_rows; i++)
    {
        for (int j = 0; j < num_cols; j++)
            data[i][j] = old.data[i][j];
    }
}
utlMatrix::~utlMatrix()
{
    for (int i = 0; i < num_rows; i++)
        delete [] data[i];
    delete [] data;
}

乘法运算符,我试过两个,如果连续两次使用,都会失败。

/*
utlMatrix operator*(const utlMatrix &left, const utlMatrix &right)
{
    // first determine if the matrices can be multiplied
    if (left.num_cols != right.num_rows)
    {
        std::cout << "Error using *, Inner dimensions must agree." << std::endl;
        exit(-1);
    }
    // create the new matrix
    utlMatrix newmat(left.num_rows, right.num_cols);
    for (int i = 0; i < left.num_rows; i++)
        for (int j = 0; j < right.num_cols; j++)
            for (int k = 0; k < right.num_rows; k++)
                newmat.data[i][j] += left.data[i][k] * right.data[k][j];
        return newmat;
}
*/
utlMatrix utlMatrix::operator*(const utlMatrix &right) const
{
        if ( this->num_cols != right.num_rows)
    {
        std::cout << "Error using *, Inner dimensions must agree." << std::endl;
        return utlMatrix();
    }
    utlMatrix newmat(this->num_rows, right.num_cols);
    for (int i = 0; i < this->num_rows; i++)
        for (int j = 0; j < right.num_cols; j++)
            for (int k = 0; k < right.num_rows; k++)
                newmat.data[i][j] += this->data[i][k] * right.data[k][j];
    return newmat; 
}

复制构造函数,赋值和加法运算符都可以正常工作。当我尝试将1个矩阵乘以另一个矩阵时,它第一次工作但第二次失败。除了在乘法后打印矩阵之外,我还在输入构造函数,运算符和析构函数时更改了代码。数学对于第一个矩阵是好的,代码失败了:

Unhandled exception at 0x776015de in sandbox.exe: 0xC0000005: Access violation writing location 0xcdcdcdcd.

从屏幕输出中我知道在第二次乘法之后调用复制构造函数时会发生这种情况。加法运算符镜像第一个乘法运算符,看起来工作正常,没有异常,复制构造函数和析构函数按预期发生。我在SO Matrix class operator overloading,destructor problemMatrix Multiplication with operator overloading上找到了2个答案。我检查确保我的指针没有被复制。复制构造函数会创建一个带有指向数据的新指针的新对象。如果我跑:

int main()
{
utlMatrix A(3,3);
utlMatrix B(2,2);
A.fill_rand();
B.fill_rand();    
B = A;
return 0;
}

调试器显示:

A   {num_rows=3 num_cols=3 data=0x000365c0 ...} utlMatrix
B   {num_rows=3 num_cols=3 data=0x00037c50 ...} utlMatrix

我错过了什么?这是我实际使用运算符的方式。在D = A * B之后发生故障;

#include "utlMatrix.h"

int main()
{
    // create the first matrices
    utlMatrix A(3,3);
    utlMatrix B(3,3);
    utlMatrix C(3,2);

    // fill them with random numbers
    A.fill_rand();
    B.fill_rand();
    C.fill_rand();

    utlMatrix D = A * B;
    utlMatrix E = A * C;
    utlMatrix F = B * C;
}

1 个答案:

答案 0 :(得分:1)

错误似乎仅在第二次或第三次调用后显示,因为那时矩阵产生非方形输出。这些行:

for (int i = 0; i < num_cols; i++)
    data[i] = new float[num_cols];
复制构造函数中的

意味着非方矩阵实际上被构建为旧矩阵的大小列的方阵。由于我的情况是一个行数多于列的矩阵,因此它试图将数据放入不存在的内存位置。根据Igor Tandetnik和Dave S的建议,修复索引并使用SWAP修复了问题。