【问题标题】:Trouble in a OOP C++ operatorOOP C++ 运算符中的问题
【发布时间】:2015-01-04 19:44:25
【问题描述】:

我对 C++ 很陌生。 我的问题是编写一个关于矩阵的 OOP C++ 程序(创建一个矩阵类并在这个类中添加一些方法) 这是我的代码:

#include <iostream>
#include <iomanip>

using namespace std;

class Matrix 
{
    private:
        int col, row;
        double *a;
    public:
        Matrix(int col = 1, int row = 1) {
            this->col = col; this->row = row;
        }
        ~Matrix() {
            delete a;
            col = row = 0;
        }
        void insertMatrix() {
            a = new double[this->col * this->row];
            for (int i = 0; i < this->row; i++)
                for (int j = 0; j < this->col; j++) {
                    cout << endl << "a[" << i + 1 << "][" << j + 1 << "] = ";
                    cin >> this->a[i * this->col + j];
                }
        }
        void printMatrix() {
            for (int i = 0; i < this->row; i++) {
                for (int j = 0; j < this->col; j++)
                    cout << setw(9) << this->a[i * this->col + j];
                cout << endl;
            }
            cout << endl;
        }
        int getCol() {
            return col;
        }
        int getRow() {
            return row;
        }
        Matrix operator+(Matrix);
        Matrix operator-(Matrix);
};

Matrix Matrix::operator+(Matrix x) {
    if (x.col != col || x.row != row) {
        cout << endl << "Can't add these two matrices";
        exit(0);
    }
    Matrix sum(x.col, x.row);
    sum.a = new double(sum.col * sum.row);
    for (int i = 0; i < this->col * this->row; i++)
        sum.a[i] = a[i] + x.a[i];
    return sum;
}

Matrix Matrix::operator-(Matrix x) {
    if (x.col != this->col || x.row != this->row) {
        cout << endl << "Can't subtract these two matrices";
        exit(0);
    }
    Matrix dif(this->col, this->row);
    dif.a = new double(dif.col * dif.row);
    for (int i = 0; i < this->col * this->row; i++)
        dif.a[i] = this->a[i] - x.a[i];
    return dif;
}

int main()
{
    int row, col;
    cout << endl << "Column = "; cin >> col; cout << endl << "Row = "; cin >> row;
    Matrix A(col, row), B(col, row);
    A.insertMatrix(); B.insertMatrix();
    cout << "Matrix A: " << endl; A.printMatrix(); 
    cout << "Matrix B: " << endl; B.printMatrix();
    cout << "Matrix (A + B)" << endl; (A + B).printMatrix();
    cout << "Matrix (A - B)" << endl; (A - B).printMatrix();
}

我看不出有任何错误。我可以编译程序。但是每次我尝试输入一些数字时,程序都会冻结并显示“停止工作”的消息并得到错误的答案。 我在 Windows 8 中使用 Orwell Dev C++。 谁能解释一下为什么?

【问题讨论】:

  • 这有点难说;您可以使用调试器或提供表现相同行为的程序的一小部分吗?
  • 好吧,实际上我尝试调试但我找不到错误。我相信 printMatrix() 方法效果很好。但是,我认为问题在于 2 方法 operator+ 和 operator- 我认为 (A + B).printMatrix() 和 (A - B).printMatrix() 存在一些问题,但我无法弄清楚。每当我删除这两行时,程序就可以了。
  • 如果您将它们注释掉,问题会消失吗?
  • 转到您的调试 -> 异常 -> win32 异常,然后单击访问冲突旁边的复选框。这将使调试器停止访问冲突。当它停止时,将调用堆栈向上移动到程序中的代码行。
  • @drescherjm 你是对的,但如果应用了三规则,这将不是问题;本地结果将被复制。

标签: c++ oop


【解决方案1】:

一个错误是您错误地使用了new

 sum.a = new double(sum.col * sum.row);

上面动态创建了一个double,并将值初始化为sum.col * sum.row

你应该使用new[]:

 sum.a = new double[sum.col * sum.row];

那么在使用new[]时必须使用delete[],而不是delete

另一个错误是您没有在构造函数中初始化a 指针。当 Matrix 被销毁时,析构函数将在指向 who-knows-where 的指针上发出delete

因此,这个简单的一行程序有问题:

int main() {
   Matrix m;
}  // < -- problems here 

解决方法是确保您的指针已初始化:

Matrix(int mcol = 1, int mrow = 1) : a(0), col(mcol), row(mrow) {}

注意a现在初始化为0。还要注意成员初始化列表的用法。

但是,另一个错误是您的Matrix 类缺少用户定义的复制构造函数和赋值运算符。当您在此处按值返回或传递Matrix 时:

Matrix Matrix::operator+(Matrix x)

复制只会对指针进行浅复制,因此您的程序会出现内存泄漏、双重释放错误等。请阅读“3 规则”:

What is The Rule of Three?

其他问题:

不要在类代码中调用exit(0)。如果我想使用您的 Matrix 类,并且我给 operator + 一个大小不正确的 Matrix,请不要关闭我的应用程序!相反,抛出异常,或发出assert()

请看这里:exit() call inside a function which should return a reference

【讨论】:

  • 只是为了澄清 - new double(sum.col * sum.row) 返回一个指向新分配的 double 的指针,并使用值 sum.col * sum.row? 初始化内存?
  • 是的,没错。让我再看一遍。非常感谢!
  • @LightnessRacesinOrbit 感谢您提供详细信息。
  • 是的,这对我来说相当棘手。我花了大约3个小时,我找不到错误。现在放心了!
  • @PeaNguyen - 我更新了我的帖子。您还有其他问题可以通过简单的单行程序查看。
【解决方案2】:

您程序中的主要问题是,在您重载的运算符中,您返回一个堆栈分配的 Matrix 对象,该对象将调用复制构造函数。

但是由于你没有定义一个,编译器会为你生成它,进行按位复制,这意味着复制对象中的 d 指针将指向同一个位置就像堆栈中的对象一样。

因此,析构函数被调用了两次

  • 离开函数重载时;
  • 在销毁复制的对象时,立即发生在此行之后:

(A + B).printMatrix();

这就是为什么你的程序会异常终止并出现类似这样的错误:

`./rez' 中的错误:free(): invalid next size (fast): 0x00000000020390c0

正如其他人所建议的,如果您遵守 3 规则(或 C++11/14 中的 5),您就不会遇到此问题。

【讨论】:

  • 更喜欢零规则。
【解决方案3】:

另一个错误是公然违反三法则;复制您的 Matrix 会破坏其所有权语义。

你为什么不改用std::vector&lt;double&gt;

【讨论】:

  • 绝对 - 在运算符中返回本地定义的结果需要自定义复制构造函数。
猜你喜欢
  • 2021-10-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2011-01-23
  • 2011-04-22
  • 2014-04-15
相关资源
最近更新 更多