使用动态分配和操作符重载的矩阵和

Sum of matrices using dynamic allocation and operator overloading

本文关键字:重载 操作符 动态分配      更新时间:2023-10-16

我写了一个代码,使用动态分配和操作符重载找到两个矩阵的和。

#include<iostream>
#include<new>
using namespace std;
class matrix
{
    int**m;
    int r;
    int c;
public:
    matrix(int a, int b)
    {
        r = a;
        c = b;
        m = new int*[r];
        for (int i = 0; i < r; i++)
            m[i] = new int[c];
    }
    ~matrix()
    {
        for (int i = 0; i < r; i++)
            delete[] m[i];
        delete[] m;
    }
    friend istream &operator>>(istream &in, matrix s);
    friend matrix operator+(matrix& m1, matrix& m2);
    friend ostream &operator<<(ostream &out, matrix s);
};
istream &operator>>(istream &in, matrix s)
{
    cout << "enter elements" << endl;
    for (int i = 0; i < s.r; i++)
    {
        for (int j = 0; j < s.c; j++)
        {
            in >> s.m[i][j];
        }
    }
    return in;
}
ostream &operator<<(ostream &out, matrix s)
{
    for (int i = 0; i < s.r; i++)
    {
        cout << " ";
        for (int j = 0; j < s.c; j++)
            out << s.m[i][j] << " ";
        cout << endl;
    }
    return out;
}
matrix operator+(matrix& m4, matrix& m5)
{
    matrix m6(m4.r, m4.c);
    for (int i = 0; i < m4.r; i++)
    {
        for (int j = 0; j < m4.c; j++)
        {
            m6.m[i][j] = m4.m[i][j] + m5.m[i][j]; //gets stuck here!
        }
    }
    return m6;
}
int main()
{
    int r, c;
    cout << "enter number of rows and columns" << endl;
    cin >> r >> c;
    matrix m1(r, c), m2(r, c), m3(r, c);
    cin >> m1;
    cin >> m2;
    m3 = m1 + m2;
    cout << m3;
    return 0;
}

当我执行时,我卡在了matrix operator+(matrix &m4,matrix &m5)

我在网上搜索,但我找不到我的错误。那么,我的代码出了什么问题?它在Code::Blocks中工作得很好,但在Xcode中不行。

我在你代码中看到的问题:

  1. 在构造函数中分配内存,在析构函数中释放内存。但是,您没有实现复制构造函数或复制赋值操作符。这会导致很多问题。

  2. operator>>的第二个参数需要是一个引用。否则,您将最终将数据读取到一个局部变量中。您用来调用它的对象不会有任何变化。

    没有实现复制构造函数的另一个不必要的副作用是,当该函数返回时,最终使用悬空指针,这是导致未定义行为的原因。

  3. operator<<的第二个参数应该是const&。否则,您将不必要地创建对象的副本并删除它。

    由于缺少复制构造函数,该函数还会导致悬空指针。

复制构造函数可以实现为:

matrix(matrix const& copy) : r(copy.r), c(copy.c)
{
   m = new int*[r];
   for (int i = 0; i < r; i++)
   {
      m[i] = new int[c];
      for (int j = 0; j < c; ++j )
      {
         m[i][j] = copy.m[i][j];
      }
   }
}

我将留给您实现复制赋值操作符

问题源于按值传递而不是按引用传递,但这暴露了完全缺乏三原则的遵从性。

R Sahu演示了复制构造函数来解决"三原则"问题。

我要走一条不同的路线:Die Array, Die !

与标准的愚蠢数组不同,std::vector符合三原则。在二维中使用它非常轻松:
std::vector<std::vector<int>> mMatrix;

Vector使这个程序规则3/5兼容,这意味着您可以复制和移动矩阵对象,大大减少调试冒险。使用数组代替vector没有任何好处,除非数组的大小是固定的,所以在使用数组之前要仔细考虑。

注意名称的变化。matrix已经被类使用了,所以稍微混淆一下名称就可以了。出于类似的原因,我做了更多的重命名:

size_t mRows; // can't have negative indexes, so why used a signed type?
size_t  mCols;

构造函数现在看起来像这样:

matrix(size_t rows, size_t cols) :
            mRows(rows), mCols(cols), mMatrix(rows, std::vector<int>(cols))
{
}

友元函数得到了轻微的修改,以获得更好的命名,并在需要的地方使用引用:

friend std::istream &operator>>(std::istream &in, matrix &out);
friend matrix operator+(matrix& rhs, matrix& lhs);
friend std::ostream &operator<<(std::ostream &out, matrix &in);

其余的基本可以保持不变。

但是有一个更好的方法:

#include<iostream>
#include<vector>
//using namespace std;
class matrix
{
    size_t mRows; // can't have negative indexes, so why used a signed type?
    size_t  mCols;
    std::vector<int> mMatrix; 
    //  the vector is one dimensional, so tyhere is much less clean-up
    // In addition, all of the data is contiguous and as cache-friendly as possible.
public:
    matrix(size_t rows, size_t cols) :
            mRows(rows), mCols(cols), mMatrix(rows * cols)
    {
    }
    int & operator()(size_t row, size_t col)
    {
        if (row >= mRows || col >= mCols)
        { // trap bad indexing. discard if speed > safety.
            throw std::out_of_range("Bad index");
        }
        return mMatrix[row * mCols + col]; // note the math
    }
    // returns a copy so the value can't be modified
    int operator()(size_t row, size_t col) const
    {
        if (row >= mRows || col >= mCols)
        { // trap bad indexing. discard if speed > safety.
            throw std::out_of_range("Bad index");
        }
        return mMatrix[row * mCols + col]; // note the math
    }
    friend std::istream &operator>>(std::istream &in, matrix &out);
    friend matrix operator+(matrix& rhs, matrix& lhs);
    friend std::ostream &operator<<(std::ostream &out, matrix &in);
};

这种布局更快,因为空间局部性有助于在工作时缓存数据。2d数组方法具有行数+1个不同的数组,这些数组可能位于RAM中非常不同的位置,这会导致缓存丢失和读取数据的时间增加,如果所有数据都在一个位置,则可能已经读取了数据。