C++:在二维数组上实现移动赋值运算符

C++:在二维数组上实现移动赋值运算符,c++,arrays,pointers,multidimensional-array,C++,Arrays,Pointers,Multidimensional Array,我有一个用来实现矩阵的类,在这里: template<typename Comparable> class Matrix { private: std::size_t num_cols_; std::size_t num_rows_; Comparable **array_; public: Matrix(); ~Matrix(); // Destructor Matr

我有一个用来实现矩阵的类,在这里:

template<typename Comparable>
class Matrix {
    private: 
        std::size_t num_cols_;
        std::size_t num_rows_;
        Comparable **array_;

    public:
        Matrix();
        ~Matrix(); // Destructor
        Matrix(const Matrix<Comparable> & rhs);// Copy constructor
        Matrix(Matrix<Comparable> && rhs); // Move constructor
        Matrix<Comparable> & operator= (const Matrix<Comparable> & rhs);// Copy assignment
        Matrix<Comparable> & operator= (Matrix<Comparable> && rhs); // Move assignment
        template<typename buh> friend std::ostream &operator<< (std::ostream &os, Matrix<buh> &rhs);
        void ReadMatrix();
};
我可以用值填充数组并访问它们,我的复制构造函数和移动赋值操作符可以正常工作,但是移动赋值操作符抛出了一个奇怪的错误。这是定义

template<typename Comparable>
Matrix<Comparable>& Matrix<Comparable>::operator= (Matrix<Comparable> && rhs) {
    delete[] array_;
    array_ = new Comparable*[rhs.num_rows_];    
    for(int i = 0;i < rhs.num_rows_;++i) {
        std::swap(array_[i],rhs.array_[i]);
        rhs.array_[i] = nullptr;
    }
    rhs.num_cols_ = 0;
    rhs.num_rows_ = 0;
    rhs.array_ = nullptr;
    return *this;
}

以语句a=std::moveb;为例;。如果b的大小与a不同,则移动会使矩阵数据变形。如果b的列数大于a,则额外的列数将被切断;如果b的行数少于a,则多余的行将保留在a中;如果a比b有更多的列或行,多余的列将显示内存地址,其中应该没有任何内容。这是一个简单的bug吗?我创建数组的方式有问题吗?如果您能深入了解造成这种情况的原因,我们将不胜感激。

不确定您为什么在移动分配操作符中使用新的Comparable*。移动分配的思想是移动资源,而不是创建新资源

您的代码可能如下所示:

delete[] array_;
array_ = rhs.array_;
rhs.array_ = nullptr;
num_cols_ = rhs.num_cols_;
num_rows_ = rhs.num_rows_;
return *this;

但是,考虑使用。这并不总是最有效的选择,但如果你不是大师,这是一个很好的起点

注意:如果您真的想使用指向指针的指针来实现您的矩阵,请使用vector。所有的工作都是为你做的;你的代码只是重新发明轮子


通常,用一个连续的分配来表示矩阵更简单、更有效,而不是为每一行单独分配,因此您可能需要考虑一下这个想法。

移动分配并不意味着仔细修改传入的对象,使其成为某种“空”值,这意味着可以修改传入的对象

这里的移动分配应该有一个非常简单的实现:只需交换

template<typename Comparable>
Matrix<Comparable>& Matrix<Comparable>::operator= (Matrix<Comparable> && rhs) {
    using std::swap;
    swap(array_, rhs.array_);
    swap(num_cols_, rhs.num_cols_);
    swap(num_rows_, rhs.num_rows_);
    return *this;
}

如果这不是家庭作业,那么答案是使用std::vector。您的移动赋值运算符1从不更新此的行和列计数,2泄漏rhs.array\u3泄漏此运算符以前持有的所有行,4执行不必要的分配。如果无法使用std::vector,请使用std::unique\u ptr,然后使用默认移动构造函数。如果您不能使用std,请在写入矩阵之前编写您自己的vector/unique_ptr。修改传入的对象是可以的,因为该对象应该保持在有效但未指定的状态,或者类似的状态。例如,执行array=rhs.array\ux;如果打电话的人在搬家后试图使用rhs,没有其他任何东西。我真的忍不住要把这些事情过分复杂化。谢谢
template<typename Comparable>
Matrix<Comparable>& Matrix<Comparable>::operator= (Matrix<Comparable> && rhs) {
    using std::swap;
    swap(array_, rhs.array_);
    swap(num_cols_, rhs.num_cols_);
    swap(num_rows_, rhs.num_rows_);
    return *this;
}