提问人:Herman Neple 提问时间:3/15/2023 最后编辑:Vlad from MoscowHerman Neple 更新时间:3/15/2023 访问量:70
自定义 Matrix 类中的复制构造函数问题
Issues with copy constructor in custom Matrix class
问:
我有一个自定义矩阵类,它本身就可以正常工作。我遇到的问题是,当我尝试创建由另一个矩阵定义的新矩阵时,不会复制整个矩阵。
矩阵本身基本上只是一个指向一维双精度数组的指针,其中我有一个自定义函数来查找正确的 m x n 索引。 我创建了一个复制构造函数并重载了 = 运算符。我认为只有矩阵的一部分被复制真的很奇怪。
问题可能在于我如何对待我的指针,因为我没有完全掌握它。
当我尝试这样做时:
Matrix m(3,10);
for(int i = 0; i<m.getColumns(); i++){
m.set(0,i, 4);
}
Matrix l(m);
Matrix c = m;
cout << m << endl;
cout << l << endl;
cout << c << endl;
我得到这个输出:
4 4 4 4 4 4 4 4 4 4
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
这是我的 Matrix.h 文件:
#pragma once
#include <iostream>
using namespace std;
class Matrix
{
private:
int r;
int c;
int getIndex(int r, int c) const;
double* matrix;
public:
Matrix(int nRows, int nColumns);
explicit Matrix(int nRows);
Matrix(const Matrix &);
~Matrix();
double get(int row, int col) const;
void set(int row, int col, double value);
int getRows() const;
int getColumns() const;
friend ostream& operator<<(ostream& os, const Matrix& m);
Matrix& operator=(Matrix rhs);
};
这是类的定义:
#include <Matrix.h>
#include <cassert>
#include <iostream>
#include <utility>
using namespace std;
Matrix::Matrix(int nRows, int mColumns)
{
assert(nRows>0 && mColumns>0);
r = nRows;
c = mColumns;
matrix = new double[r*c]{};
//fills with zeros
for(int i = 0; i<r*c; i++){
matrix[i] = 0;
}
}
Matrix::Matrix(int nRows)
{
assert(nRows>0);
r = nRows;
c = nRows;
matrix = new double[r*c]{};
for(int i = 0; i<r*c; i++){
matrix[i] = 0;
}
//Makes the identity matrix
for(int i = 0; i<r; i++){
set(i,i, 1);
}
}
Matrix::Matrix(const Matrix& other){
r = other.getRows();
c = other.getColumns();
matrix = new double[r*c];
*matrix = *other.matrix;
}
int Matrix::getIndex(int row, int col) const
{
int index = row*c;
index += col;
return index;
}
int Matrix::getRows() const
{
return r;
}
int Matrix::getColumns() const
{
return c;
}
void Matrix::set(int row, int col, double value){
matrix[getIndex(row, col)] = value;
}
double Matrix::get(int row, int col) const{
return matrix[getIndex(row,col)];
}
Matrix::~Matrix()
{
}
ostream& operator<<(ostream& os, const Matrix& m){
for(int i = 0; i<m.getRows(); i++){
for(int j = 0; j<m.getColumns(); j++){
os << m.get(i,j);
os << ' ';
}
os << '\n';
}
os << endl;
return os;
}
Matrix& Matrix::operator=(Matrix rhs){
r = rhs.r;
c = rhs.c;
swap(matrix, rhs.matrix);
return *this;
}
答:
0赞
PaulMcKenzie
3/15/2023
#1
这不会将数据从一个数组复制到另一个数组:
*matrix = *other.matrix;
需要一个循环来复制数据,或者使用:memcpy
std::copy
std::copy(other.matrix, other.matrix + r*c, matrix);
2赞
Vlad from Moscow
3/15/2023
#2
copy 构造函数中的此语句
*matrix = *other.matrix;
相当于
matrix[0] = other.matrix[0];
也就是说,它只设置新创建的数组的一个元素,但您需要复制所有元素。
例如,您可以使用 for 循环
for ( int i = 0; i < r * c; i++ )
{
matrix[i] = pther.matrix[i];
}
或者,您可以使用标头中声明的标准算法std::copy
<algorithm>
#include <algorithm>
//...
std::copy( other.matrix, other.matrix + r * c, matrix );
由于您使用的是基本类型 double,因此您还可以使用标头中声明的标准 C 函数,例如memcpy
<cstring>
#include <cstring>
//...
std::memcpy( matrix, other.matrix, r * c * sizeof( double ) );
此外,析构函数应释放分配的内存
Matrix::~Matrix()
{
delete [] matrix;
}
否则,复制赋值运算符定义如下
Matrix& Matrix::operator=(Matrix rhs){
r = rhs.r;
c = rhs.c;
swap(matrix, rhs.matrix);
return *this;
}
将产生内存泄漏。
在这个构造函数中
Matrix::Matrix(int nRows, int mColumns)
{
assert(nRows>0 && mColumns>0);
r = nRows;
c = mColumns;
matrix = new double[r*c]{};
//fills with zeros
for(int i = 0; i<r*c; i++){
matrix[i] = 0;
}
}
this for 循环
//fills with zeros
for(int i = 0; i<r*c; i++){
matrix[i] = 0;
}
是多余的。在此语句中,已分配数组的元素已设置为零
matrix = new double[r*c]{};
评论
*matrix = *other.matrix;
这不是复制 C 样式数组的方法。您将更容易使用原始指针和 C 样式数组。std::vector
Matrix
operator=
matrix
std::vector
std::vector
Matrix::~Matrix() { }
-- 确切地说,您要求析构函数正常工作并调用数据。由于您在赋值运算符中使用并按值传递,因此在赋值运算符中工作的所有内容都基于要正确编码的复制构造函数和析构函数。否则,您的程序会损坏。operator=
Matrix
delete[]
swap
Matrix