使用动态分配和运算符重载的矩阵之和

时间:2015-08-31 21:20:19

标签: c++

我编写了一个代码,使用动态分配和运算符重载来查找两个矩阵的总和。

#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中没有。

2 个答案:

答案 0 :(得分:1)

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

  1. 您有代码在构造函数中分配内存并在析构函数中释放内存。但是,您尚未实现复制构造函数或复制赋值运算符。这导致了很多问题。请参阅The Rule of Three

  2. operator>>的第二个参数需要作为参考。否则,您最终会将数据读入局部变量。您以前调用它的对象不会有任何更改。

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

  3. operator<<的第二个参数应为const&。否则,您将不必要地复制该对象并将其删除。

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

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

    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];
          }
       }
    }
    

    我将让您实现复制赋值运算符。

答案 1 :(得分:0)

问题源于价值转移而不是参考传递,但这暴露了完全缺乏Rule of Three合规性。

R Sahu已经演示了复制构造函数来解决三元法则问题。

我将采取不同的路线:Die Array,DIE!

与标准的愚蠢数组不同,std::vector符合三级规则。将它用于2维是非常轻松的:

std::vector<std::vector<int>> mMatrix;

Vector使该程序规则符合3/5标准,这意味着您可以通过大幅减少调试冒险来复制和移动Matrix对象。除非数组具有固定大小,否则您不会使用数组而不是向量,因此在使用数组之前请仔细考虑。

请注意名称的更改。 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);

};

这种布局要快得多,因为spatial locality在您工作时协助缓存数据。 2 D阵列方法具有行数+1不同的阵列,可能在RAM中的位置非常不同,导致cache misses的增加和读取数据的时间损失,如果所有数据都是在一个地方。