C++-我的move/copy构造函数和move/copy赋值运算符有什么问题



所以我有自己的矩阵类,我试图重载类的++=运算符,如下所示:

template <class T>
void Matrix<T>::operator+=(Matrix& mat) {
if (this->m_rows != mat.m_rows || this->m_cols != mat.m_cols) {
cerr << "Matrix rows/cols don't match" << endl;
}
else {
for (unsigned int i = 0; i < this->m_rows; i++) {
for (unsigned int j = 0; j < this->m_cols; j++) {
this->m_vec[i * this->m_cols + j] += mat.m_vec[i * this->m_cols + j];
}
}
}
}
template <class T>
Matrix<T> operator+(Matrix<T> mat1, Matrix<T>& mat2) {
if (mat1.get_rows() != mat2.get_rows() || mat1.get_cols() != mat2.get_cols()) {
cerr << "Matrix rows/cols don't match" << endl;
}
else {
mat1 += mat2;
return mat1;
}
}

(我试图使+运算符可链接,+=运算符不可链接。矩阵由一维数组表示(

然而,当我尝试添加两个矩阵时,程序拒绝添加它们(没有错误消息(。我怀疑我的移动/复制构造函数、移动/复制赋值运算符或析构函数可能有问题,但我不知道出了什么问题。

// Copy constructor
template <class T>
Matrix<T>::Matrix(Matrix& obj) {
size_t rows = obj.get_rows();
size_t cols = obj.get_cols();
this->m_rows = rows;
this->m_cols = cols;
this->m_capacity = rows * cols;
this->m_vec = new T[rows * cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
this->m_vec[j + i * cols] = obj(i, j);
}
}
}
// Move constructor
template <class T>
Matrix<T>::Matrix(Matrix&& obj)
: m_rows(0)
, m_cols(0)
, m_capacity(0)
, m_vec(nullptr)
{
m_rows = obj.get_rows();
m_cols = obj.get_cols();
m_capacity = obj.get_capacity();
m_vec = obj.m_vec;
obj.m_rows = 0;
obj.m_cols = 0;
obj.m_capacity = 0;
obj.m_vec = nullptr;
}
// Destructor
template <class T>
Matrix<T>::~Matrix() {
delete[] m_vec;
}
// Copy assignment operator
template <class T>
Matrix<T>& Matrix<T>::operator=(const Matrix& obj)
{
m_rows = obj.get_rows();
m_cols = obj.get_cols();
m_capacity = obj.get_capacity();
m_vec = obj.m_vec;
return *this;
}
// Move assignment operator
template <class T>
Matrix<T>& Matrix<T>::operator=(Matrix&& obj)
{
if (this != &obj)
{
delete[] m_vec;
m_rows = obj.get_rows();
m_cols = obj.get_cols();
m_capacity = obj.get_capacity();
m_vec = obj.m_vec;
obj.m_rows = 0;
obj.m_cols = 0;
obj.m_capacity = 0;
obj.m_vec = nullptr;
}
return *this;
}
// Matrix class properties
class Matrix{
private:
size_t m_rows;
size_t m_cols;
size_t m_capacity;
T* m_vec;
}

我对C++还很陌生,这是我第一次尝试创建复制/移动构造函数/赋值运算符,所以我可能缺少一些明显的东西。也许我把这件事搞得过于复杂了。有没有一种更简单/更好的方法来编写移动/复制构造函数和赋值运算符?你能发现这里有什么奇怪的地方吗?对我来说似乎很好…

谢谢!

编辑:我现在已经尝试按照@eerorika的建议更改副本分配运算符,但我的++=运算符仍然不起作用(和以前一样(。可以肯定的是,我还尝试以与编辑复制赋值运算符相同的方式编辑移动赋值运算符和移动构造函数,但仍然。。。没有什么以下是经过编辑的版本

// Move constructor
template <class T>
Matrix<T>::Matrix(Matrix&& obj)
: m_rows(0)
, m_cols(0)
, m_capacity(0)
, m_vec(nullptr)
{
this->m_rows = obj.get_rows();
this->m_cols = obj.get_cols();
this->m_capacity = obj.get_capacity();
//m_vec = obj.m_vec;
this->m_vec = new T[obj.get_rows() * obj.get_cols()];
for (int i = 0; i < obj.get_rows(); i++) {
for (int j = 0; j < obj.get_cols(); j++) {
this->m_vec[j + i * obj.get_cols()] = obj.m_vec[i * this->m_cols + j];
}
}
obj.m_rows = 0;
obj.m_cols = 0;
obj.m_capacity = 0;
obj.m_vec = nullptr;
}
// Move assigment operator
template <class T>
Matrix<T>& Matrix<T>::operator=(Matrix&& obj)
{
// If the address of the object being passed in is the same as "this", do nothing.
if (this != &obj)
{
delete[] m_vec;
this->m_rows = obj.get_rows();
this->m_cols = obj.get_cols();
this->m_capacity = obj.get_capacity();
//m_vec = obj.m_vec;
this->m_vec = new T[obj.get_rows() * obj.get_cols()];
for (int i = 0; i < obj.get_rows(); i++) {
for (int j = 0; j < obj.get_cols(); j++) {
this->m_vec[j + i * obj.get_cols()] = obj.m_vec[i * this->m_cols + j];
}
}
obj.m_rows = 0;
obj.m_cols = 0;
obj.m_capacity = 0;
obj.m_vec = nullptr;
}
return *this;
}
// Copy assignment operator
template <class T>
Matrix<T>& Matrix<T>::operator=(Matrix& obj)
{
this->m_rows = obj.get_rows();
this->m_cols = obj.get_cols();
this->m_capacity = obj.get_capacity();
//m_vec = obj.m_vec;
this->m_vec = new T[obj.get_rows() * obj.get_cols()];
for (int i = 0; i < obj.get_rows(); i++) {
for (int j = 0; j < obj.get_cols(); j++) {
this->m_vec[j + i * obj.get_cols()] = obj.m_vec[i * this->m_cols + j];
}
}
return *this;
}

你知道现在可能出了什么问题吗?你确定我的++=运算符中的代码没有问题吗?帮助

编辑2:

由于@numzero的请求,我将添加我的operator()的代码

template <class T>
T& Matrix<T>::operator()(unsigned int row, unsigned int col) {
if (row > this->m_rows || col > this->m_cols) {
cerr << "index out of range" << endl;;
}
return this->m_vec[(row - 1) * m_cols + (col - 1)];
}

我的move/copy构造函数和move/***赋值运算符s出了什么问题?

据我所知,没什么大不了的。一个小问题是,您不必要地直接在成员初始化器列表中分配本可以使用这些值初始化的成员。

我的复制分配运算符s有什么问题?

您的析构函数会删除成员指针。因此,您必须维护一个类不变量,即类的每个实例都具有指针的唯一所有权,即没有其他实例具有相同的指针值。否则,各个对象的析构函数将试图删除相同的指针,这将导致未定义的行为。

您的复制-分配运算符复制违反该类不变量的指针。请参阅您的复制构造函数,以获取您应该做什么的示例。


额外建议:永远不要像这里那样使用拥有裸指针。请改用智能指针或RAII容器,如std::vector

复制赋值操作符复制m_vec指针,而不是复制其内容(就像复制构造函数一样(。

最新更新