C++空复制赋值运算符复制数据
c++ empty copy assignment operator copies data
我是 c++ 的新手,想编写一个小型矩阵库,它有一个基础 class Matrix
,其中有一些新的矩阵类型,如 SparseMatrix
、DenseMatrix
、HashMatrix
等
我的基地class是这样的:
class Matrix {
protected:
int m,n;
public:
Matrix(int m_p, int n_p) : m(m_p), n(n_p){
std::cout << "gen constr" << std::endl;
}
Matrix(Matrix& other) = delete;
Matrix() = delete;
virtual ~Matrix() {}
int getM() const {
return m;
}
int getN() const {
return n;
}
virtual double& get(int m, int n) = 0;
virtual double get(int m, int n) const = 0;
inline double& operator() (int m, int n){
return get(m,n);
}
inline double operator() (int m, int n) const{
return get(m,n);
}
friend std::ostream &operator<<(std::ostream &os, Matrix &matrix) {
using std::scientific;
using std::fixed;
os << std::fixed << std::setprecision(2) << scientific << std::setfill(' ');
for(int i = 1; i <= matrix.getM(); i++){
for(int j = 1; j <= matrix.getN(); j++){
os << std::setw(10) << matrix.get(i,j) << " ";
}
os << "\n";
}
return os;
}
Matrix& operator=(const Matrix& other) {
// std::cout << "equality assign" << std::endl;
return *this;
}
};
如您所见,我已经覆盖了相等赋值运算符,它只是 returns 对象,实际上并不复制值。
我对 DenseMatrix
的第一个实现非常简单:
class DenseMatrix : public Matrix{
private:
double* data;
public:
DenseMatrix(int mP, int nP) : Matrix(mP, nP){
std::cout << "gen constr base" << std::endl;
this->data = new double[mP * nP]{0};
}
DenseMatrix() = delete;
~DenseMatrix() {
delete this->data ;
}
double &get(int m, int n) {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
double get(int m, int n)const {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
};
此外 main()
函数如下所示:
DenseMatrix mat(3,3);
for(int i = 1; i<= 3; i++){
mat(i,i) = i;
}
DenseMatrix mat2(3,3);
mat2 = mat;
std::cout << mat << std::endl;
std::cout << mat2 << std::endl;
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
如你所见,我首先创建了两个矩阵。我调整了第一个矩阵的值并将第二个矩阵的值保留为默认值 0。但是在调用相等赋值运算符之后,即使我实现的函数基本上没有影响矩阵的代码,第二个矩阵的内容也会发生变化。
我不明白这种行为,如果有人能简要解释一下这里发生的事情,我会很高兴。
非常感谢您的耐心等待和帮助:)
您尚未为 DenseMatrix
删除或定义 operator=
复制赋值运算符,因此编译器将为您合成一个。此函数将对数据成员进行成员明智的复制,在本例中为 double *data
。由于指针将指向 mat
和 mat2
中的相同内容,因此打印出来时会看到相同的内容。
请注意,这可能不是您想要的。一个问题是您的 DenseMatrix
析构函数将 delete
data
两次,可能导致段错误。
您没有为 DenseMatrix
定义赋值运算符。
隐式生成的赋值运算符对子对象进行赋值。基础子对象将使用 Matrix
的重载赋值运算符进行分配,因此存储在基础中的维度不会被修改 - 但您已将维度指定为相同,因此它们将被分配相同的无论如何值。
我是 c++ 的新手,想编写一个小型矩阵库,它有一个基础 class Matrix
,其中有一些新的矩阵类型,如 SparseMatrix
、DenseMatrix
、HashMatrix
等
我的基地class是这样的:
class Matrix {
protected:
int m,n;
public:
Matrix(int m_p, int n_p) : m(m_p), n(n_p){
std::cout << "gen constr" << std::endl;
}
Matrix(Matrix& other) = delete;
Matrix() = delete;
virtual ~Matrix() {}
int getM() const {
return m;
}
int getN() const {
return n;
}
virtual double& get(int m, int n) = 0;
virtual double get(int m, int n) const = 0;
inline double& operator() (int m, int n){
return get(m,n);
}
inline double operator() (int m, int n) const{
return get(m,n);
}
friend std::ostream &operator<<(std::ostream &os, Matrix &matrix) {
using std::scientific;
using std::fixed;
os << std::fixed << std::setprecision(2) << scientific << std::setfill(' ');
for(int i = 1; i <= matrix.getM(); i++){
for(int j = 1; j <= matrix.getN(); j++){
os << std::setw(10) << matrix.get(i,j) << " ";
}
os << "\n";
}
return os;
}
Matrix& operator=(const Matrix& other) {
// std::cout << "equality assign" << std::endl;
return *this;
}
};
如您所见,我已经覆盖了相等赋值运算符,它只是 returns 对象,实际上并不复制值。
我对 DenseMatrix
的第一个实现非常简单:
class DenseMatrix : public Matrix{
private:
double* data;
public:
DenseMatrix(int mP, int nP) : Matrix(mP, nP){
std::cout << "gen constr base" << std::endl;
this->data = new double[mP * nP]{0};
}
DenseMatrix() = delete;
~DenseMatrix() {
delete this->data ;
}
double &get(int m, int n) {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
double get(int m, int n)const {
int index = m*getN()+n-(getN()+1);
assert(index < (getN() * getM()) && index >= 0);
return this->data [index];
}
};
此外 main()
函数如下所示:
DenseMatrix mat(3,3);
for(int i = 1; i<= 3; i++){
mat(i,i) = i;
}
DenseMatrix mat2(3,3);
mat2 = mat;
std::cout << mat << std::endl;
std::cout << mat2 << std::endl;
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
>>> 1.00e+00 0.00e+00 0.00e+00
>>> 0.00e+00 2.00e+00 0.00e+00
>>> 0.00e+00 0.00e+00 3.00e+00
如你所见,我首先创建了两个矩阵。我调整了第一个矩阵的值并将第二个矩阵的值保留为默认值 0。但是在调用相等赋值运算符之后,即使我实现的函数基本上没有影响矩阵的代码,第二个矩阵的内容也会发生变化。
我不明白这种行为,如果有人能简要解释一下这里发生的事情,我会很高兴。
非常感谢您的耐心等待和帮助:)
您尚未为 DenseMatrix
删除或定义 operator=
复制赋值运算符,因此编译器将为您合成一个。此函数将对数据成员进行成员明智的复制,在本例中为 double *data
。由于指针将指向 mat
和 mat2
中的相同内容,因此打印出来时会看到相同的内容。
请注意,这可能不是您想要的。一个问题是您的 DenseMatrix
析构函数将 delete
data
两次,可能导致段错误。
您没有为 DenseMatrix
定义赋值运算符。
隐式生成的赋值运算符对子对象进行赋值。基础子对象将使用 Matrix
的重载赋值运算符进行分配,因此存储在基础中的维度不会被修改 - 但您已将维度指定为相同,因此它们将被分配相同的无论如何值。