我试图使用多维数组添加两个矩阵,并使加法运算符'+'和赋值运算符'='重载,但是,垃圾数据被传递给了我重载的赋值运算符函数。
我一直在阅读有关“复制和交换惯用语”的内容,但似乎无法找到解决问题的方法,因此,我宁愿单独使用+和=,而不是使用“ + =”我见过有人这样做,因为我将对矩阵使用其他算术,但是我想首先解决这个问题。
这是我的标题:
#ifndef Matrix_h
#define Matrix_h
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <utility>
class Matrix
{
private:
int row;
int column;
double ** elements;
public:
Matrix();
Matrix(int r, int c); //constructor
Matrix(const Matrix& src); //copy constructor
~Matrix(); //destructor
Matrix& operator=(const Matrix& right); // assignment operator
int getRow() const;
int getColumn() const;
void setElement(int r, int c, double data);
double getElement(int r, int c) const;
Matrix& operator+(const Matrix& right); // calculates the sum of two matrices
};
#endif
这是我的函数定义:
#include <string.h>
#include "matrix.h"
using namespace std;
Matrix::Matrix(int r, int c){ //defines the constructor to create a new matrix
row = r;
column = c;
elements = new double*[row];
for (int i=0; i<row; i++){
elements[i] = new double[column];
}
for (int i=0; i<row; i++){
for (int j=0; j<column; j++){
elements[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& src){ //defines the copying constructor
row = src.row;
column = src.column;
elements = new double*[row];
for (int i=0; i<row; i++){
elements[i] = new double[column];
}
for (int i=0; i<row; i++){
for (int j=0; j<column; j++){
elements[i][j] = src.elements[i][j];
}
}
}
Matrix::~Matrix() { //defines the destructor
for (int i=0; i<row; i++){
delete[] elements[i];
}
delete[] elements;
};
void Matrix::setElement(int r, int c, double data) {
elements[r][c] = data;
};
double Matrix::getElement(int r, int c) const {
return elements[r][c];
}
int Matrix::getColumn() const {
return column;
}
int Matrix::getRow() const {
return row;
}
Matrix& Matrix::operator =(const Matrix& right) {
if(this->elements != right.elements && column==right.column && row==right.row)
{
memcpy ( &this->elements, &right.elements, sizeof(this->elements) );
}
return *this;
}
Matrix& Matrix::operator +(const Matrix& right) {
// first, make sure matrices can be added. if not, return original matrix
if (this->row != right.row || this->column != right.column){
cout << "Matrix sizes do not match.";
return (*this);
}
Matrix sum(row, column);
for (int i=0; i<this->row; i++){
for (int j=0; j<this->column; j++){
sum.elements[i][j] = this->elements[i][j] + right.elements[i][j];
}
}
return sum;
}
我的主干简单地创建了一个4x4矩阵为1s的matrixA和一个矩阵4B的矩阵为2s的4x4并将它们添加到sum = matrixC处,这将导致一个4x4的3s矩阵。但是,这是我的结果:
matrixA
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
matrixB
2 2 2 2
2 2 2 2
2 2 2 2
2 2 2 2
matrixC before addition
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
matrixC after addition
1.0147e-316 3 3 3
1.0147e-316 3 3 3
1.0147e-316 3 3 3
1.0147e-316 3 3 3
当我测试它以查看将哪些元素传递给'='函数中的'right'时,我注意到与matrixC第一列相似的数据。我认为我不完全理解此处涉及的引用的传递,因此我希望对此有所帮助。
答案 0 :(得分:2)
嗯,我的CLang编译器警告我operator +(const Matrix& right)
返回对未定义行为的临时引用。
您必须返回一个普通对象而不是引用:
Matrix operator=(const Matrix& right); // assignment operator
答案 1 :(得分:2)
Matrix& Matrix::operator +(const Matrix& right) {
// ...
Matrix sum(row, column);
// ...
return sum;
}
您要返回对自动本地(sum
)的引用。
您可以看到算术运算符here的规范形式,并且加法应类似于
Matrix Matrix::operator+(const Matrix &b) const;
还有许多其他问题,在其他答案中也有提到,但是您当前的operator+
唯一可靠产生的就是不确定的行为。
答案 2 :(得分:2)
您的赋值运算符已损坏(并且在逻辑上有缺陷)。
从逻辑上讲,这是有缺陷的,因为无论m1 = m2
的先前状态如何,m1 == m2
之类的赋值都将导致m1
。您的实现仅在大小相同时尝试复制。您应该在作业左侧调整矩阵的大小。
您的操作员还没有正确使用memcpy
。 memcpy(dest, src, count)
会将连续数据从地址src
复制到地址dest
。您提供的地址是指向int 的指针的指针的地址,指向int
连续块的 not 指针的指针的地址。这里memcpy
根本就没有任何线索可分为两个层次。另外,sizeof(this->elements)
是sizeof(int**)
,这将是大约4或8个字节的常数,这似乎也错了。要解决此问题,我只使用一组简单的for
循环即可。
Matrix& Matrix::operator=(const Matrix& other){
// attempt to acquire memory before modifying (for exception safety)
int** temp = new int*[other.row];
for (int i = 0; i < other.row; ++i){
temp[i] = new int[other.col];
}
// cleanup
for (int i = 0; i < row; ++i){
delete[] elements[i];
}
delete[] elements;
// copy data
elements = temp;
row = other.row;
col = other.col;
for (int i = 0; i < row; ++i){
for (int j = 0; j < col; ++j){
elements[i][j] = other.elements[i][j];
}
}
return *this
}
另一个重要说明:您的operator+
返回对局部变量的引用。这非常糟糕,但是C++ doesn't protect you from it。您应该只按值返回sum
。
在现代C ++中,我们通常更喜欢使用std::vector<std::vector<int>>
之类的替代手动内存管理的更安全的方法,这可以无缝地强制正确使用并从您身上救出自己。
答案 3 :(得分:0)
一个提示:如果将矩阵存储为一个数组double m[rows * columns]
,则实现将更加简单。
索引[row][column]
为m[row * columns + column]
。
求和只是将两个数组按元素求和(本质上是向量求和)。