【发布时间】:2021-06-17 09:36:57
【问题描述】:
我正在尝试学习编写自定义构造函数的基础知识,但我无法弄清楚我做错了什么。我知道就我的目的而言,让编译器完成它的工作就足够了,但我很好奇如何修复我的定义。
#include <iostream>
#include <stdexcept>
class Matrix {
public:
Matrix(int rows, int cols); //my custom constructor
~Matrix(); //my custom destructor
Matrix(const Matrix& m); //my custom copy constructor
Matrix& operator= (const Matrix& m); //my custom assignment operator
private:
int rows_, cols_;
double* data_;
};
Matrix::Matrix(int rows, int cols): rows_ (rows), cols_ (cols){
if (rows == 0 || cols == 0)
throw std::out_of_range("Matrix constructor has 0 size");
data_ = new double[rows * cols];
}
Matrix::~Matrix()
{
delete[] data_;
}
Matrix::Matrix(const Matrix& m) : rows_(m.rows_), cols_(m.cols_)
{
data_ = new double[rows_ * cols_];
data_=m.data_;
}
Matrix& Matrix::operator=(const Matrix& m){
if(this != &m){
double* newdata_=new double[m.cols_*m.rows_];
*newdata_=*data_;
delete[] data_;
data_=newdata_;
rows_=m.rows_;
cols_=m.cols_;
}
return *this;
}
然后在程序的主体部分:
int main(){
Matrix m1(2,2);//creating a matrix of size 2x2
Matrix m2=m1; //this doesn't work
Matrix m3(m1); //nor this
return 0;
}
运行可执行文件时的错误是: free(): 在 tcache 2 中检测到双重空闲
我认为复制构造函数和赋值运算符都不会导致调用析构函数是否正确?这是为什么呢?
【问题讨论】:
-
*data_ = *m.data_;只会复制数组第一个元素的值,对吧?这实际上是仅让编译器完成其工作是不够的,因为它不会执行data_的深层复制。 -
但基本上至少存在三个问题:
data_ = m.data_;复制的是指针,而不是数组的值。*newdata_ = *data_;也没有对数组进行完整的复制。在一些地方,您实际上不会从m复制值:您的复制构造函数没有在LHS 中设置rows_或cols_,并且您永远不会在赋值运算符中访问m.data_。所以你会发生内存泄漏和双重删除,因为你实际上并没有复制数组。 -
data_ = new double[rows_ * cols_]; data_=m.data_;-- 你在连续的行中执行此操作。您已经在第一行中分配了数据,但是第二行通过再次更改data_来清除所有这些数据。所以很明显这是错误的。 -
复制构造函数中的
data_=m.data_;行是您代码中实际拥有的吗?与您的副本分配的*newdata_=*data_;相比,它看起来有点不一致。 (虽然它设法避免了双重释放,但并不是说复制分配正确地做事......)你希望这行代码完成什么?
标签: c++ constructor destructor copy-constructor