簡體   English   中英

C++ - 我的移動/復制構造函數和移動/復制賦值運算符有什么問題?

[英]C++ - What is wrong with my move/copy constructors and move/copy assign operators?

所以我有我自己的矩陣類,我試圖像這樣重載該類的++=運算符:

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)];
}

有什么不對我的移動/拷貝構造函數和移動/ ****分配 操作 符?

據我所知,沒有什么嚴重的。 一個小問題是您不必要地分配了您可以直接在成員初始化列表中使用這些值初始化的成員。

我的復制賦值運算符 s 有 什么問題?

您的析構函數刪除成員指針。 因此,您必須維護一個類不變性,即該類的每個實例都具有唯一的指針所有權,即沒有其他實例具有相同的指針值。 否則,各個對象的析構函數將嘗試刪除相同的指針,從而導致未定義的行為。

您的復制賦值運算符復制違反該類不變量的指針。 有關您應該做什么的示例,請參閱您的復制構造函數。


額外建議:永遠不要像這里那樣使用擁有裸指針。 改用智能指針或 RAII 容器,例如std::vector

您的復制賦值運算符復制m_vec指針,而不是復制其內容(就像復制構造函數那樣)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM