我编写了一个代码,使用动态分配和运算符重载来查找两个矩阵的总和。
#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中没有。
答案 0 :(得分:1)
我在您的代码中看到的问题:
您有代码在构造函数中分配内存并在析构函数中释放内存。但是,您尚未实现复制构造函数或复制赋值运算符。这导致了很多问题。请参阅The Rule of Three。
operator>>
的第二个参数需要作为参考。否则,您最终会将数据读入局部变量。您以前调用它的对象不会有任何更改。
未实现复制构造函数的另一个不必要的副作用是,当此函数返回时,您最终会使用悬空指针,这是导致未定义行为的原因。
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];
}
}
}
我将让您实现复制赋值运算符。
答案 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的增加和读取数据的时间损失,如果所有数据都是在一个地方。