C++ 如何作为类的私有成员为unique_ptr实现移动构造函数和运算符

C++ 如何作为类的私有成员为unique_ptr实现移动构造函数和运算符,c++,smart-pointers,move-semantics,move-constructor,C++,Smart Pointers,Move Semantics,Move Constructor,我正在尝试写矩阵类。我使用unique_ptr作为存储指针数组。但这个独特的ptr是类的私有成员。我想将move构造函数添加到我的矩阵类中。但是我需要私有unique_ptr的getter函数,但是当我将unique_ptr作为常量变量返回时,我不能使用std::move,但是当我返回getter函数而不使用常量引用时,编译器不允许这样做 Matrix.hpp template <typename _T> class Matrix_ { private:

我正在尝试写矩阵类。我使用unique_ptr作为存储指针数组。但这个独特的ptr是类的私有成员。我想将move构造函数添加到我的矩阵类中。但是我需要私有unique_ptr的getter函数,但是当我将unique_ptr作为常量变量返回时,我不能使用std::move,但是当我返回getter函数而不使用常量引用时,编译器不允许这样做

Matrix.hpp

template <typename _T>
    class Matrix_
    {
    private:
        size_t rows_;
        size_t cols_;
        size_t size_;
        std::unique_ptr<_T[]> data_;        
    public:
        Matrix_();
        Matrix_(const Matrix_& _m); //Copy constructor
        Matrix_(Matrix_&& _m) noexcept; //Move constructor
        Matrix_(const size_t& rows);
        Matrix_(const size_t& rows,const size_t& cols);
        Matrix_(const size_t& rows,const size_t& cols,const _T& val);
        //Operators        
        Matrix_& operator=(const Matrix_& _m); //Copy assignment
        Matrix_& operator=(Matrix_&& _m) noexcept; //Move assignment
        //
        //Methods
        size_t getRows()const;
        size_t getCols()const;
        size_t getSize()const;
        const std::unique_ptr<_T[]>& getData()const;
        void copyData(const std::unique_ptr<_T[]>& _data);

        void fill(const _T& val);
        //
        ~Matrix_();
    };
    template <typename _T>
    Matrix_<_T>::Matrix_():rows_(1),cols_(1),size_(rows_*cols_),data_(std::make_unique<_T[]>(size_))
    {
    }
    template <typename _T>
    Matrix_<_T>::Matrix_(const Matrix_& _m):rows_(_m.getRows()),cols_(_m.getCols()),size_(rows_*cols_),data_(std::make_unique<_T[]>(size_))
    {
    }
    template <typename _T>
    Matrix_<_T>::Matrix_(Matrix_&& _m)noexcept:rows_(_m.getRows()),cols_(_m.getCols()),size_(rows_*cols_),data_(std::move(_m.getData()))
    {
    }
    template <typename _T>
    Matrix_<_T>::Matrix_(const size_t& rows):rows_(rows),cols_(1),size_(rows_*cols_),data_(std::make_unique<_T[]>(size_))
    {
    }
    template <typename _T>
    Matrix_<_T>::Matrix_(const size_t& rows,const size_t& cols):rows_(rows),cols_(cols),size_(rows_*cols_),data_(std::make_unique<_T[]>(size_))
    {
    }
    template <typename _T>
    Matrix_<_T>::Matrix_(const size_t& rows,const size_t& cols,const _T& val):rows_(rows),cols_(cols),size_(rows_*cols_),data_(std::make_unique<_T[]>(size_))
    {
        fill(val);
    }
    //Operators
    template <typename _T>
    Matrix_<_T>& Matrix_<_T>::operator=(const Matrix_& _m)
    {   
        rows_ = _m.rows_;
        cols_ = _m.cols_;
        size_ = rows_*cols_;
        data_ = std::make_unique<_T[]>(size_);
        copyData(_m.getData());
        return *this;
    }
    template <typename _T>
    Matrix_<_T>& Matrix_<_T>::operator=(Matrix_&& _m)noexcept{
        rows_ = _m.rows_;
        cols_ = _m.cols_;
        size_ = rows_*cols_;
        data_ = std::move(_m.getData());
        return *this;
    }
    //
    //Methods
    template <typename _T>size_t Matrix_<_T>::getRows()const{return rows_;}
    template <typename _T>size_t Matrix_<_T>::getCols()const{return cols_;}
    template <typename _T>size_t Matrix_<_T>::getSize()const{return size_;}    
    template <typename _T>const std::unique_ptr<_T[]>& Matrix_<_T>::getData()const{return data_;}
    template <typename _T>void Matrix_<_T>::copyData(const std::unique_ptr<_T[]>& _data){        
        for(uint i=0;i<size_;i++){data_[i]=_data[i];}
    }
    template <typename _T>void Matrix_<_T>::fill(const _T& val){
        for(uint i=0;i<size_;i++){data_[i]=val;}
    }
    //
    template <typename _T>
    Matrix_<_T>::~Matrix_()
    {
    }
Test.cpp

int main()
{
   Matrix_<double> a(10,10,5.0);
   Matrix_<double> b(10,10);
   b = std::move(a);
   std::cout<<b.getData()[0]<<std::endl;

   return 0;
}
错误

做:

 template <typename _T>
    Matrix_<_T>& Matrix_<_T>::operator=(Matrix_&& _m) noexcept {
        rows_ = _m.rows_;
        cols_ = _m.cols_;
        size_ = rows_*cols_;
        data_ = std::move(_m.data_);
        return *this;
    }

将修复代码。您不需要在类内使用getter函数,仅当您希望访问类外的成员时才需要使用。不要在移动构造函数或移动赋值中使用getter。直接使用会员即可。我可能会为所有成员这样做,以使他们明显匹配

template <typename T>
Matrix<T>::Matrix(Matrix &&m) noexcept :
    rows_(m.rows_), cols_(m.cols_), size_(m.size_), data_(std::move(m.data_))
{
   // changes needed to m?
}

template <typename T>
Matrix<T>& Matrix<T>::operator=(Matrix &&m) noexcept
{
    rows_ = m.rows_;
    cols_ = m.cols_;
    size_ = m.size_;
    data_ = std::move(m.data_);
    // changes needed to m?
    return *this;
}

一个类总是可以访问它自己的成员,不管他们通过哪个对象访问

一定要考虑到它现在应该发生什么,因为它的数据是空指针。它的行、列和大小应该设置为零,还是无关紧要?通常,“从对象移动”应该保持有效但未指定的状态,无论您决定这对类意味着什么。至少,调用析构函数应该是有效的,并将其分配给其他对象应该按照预期工作;事实已经如此


因为这里不需要getter,所以一个单独的问题是,公共接口是否应该包含getter,或者它是否应该具有更方便的返回类型,比如const t*或t*

为什么需要一个getter来表示内部数据,以及在getter调用之后,谁应该是该数据的所有者?它应该仍然归Matrix_uu所有,还是getter调用者应该成为数据的唯一所有者?所有者必须相同我需要getter来访问参数的数据成员,例如'Matrix_uuu::Matrix_uuu&&m',我需要访问_m的数据变量这是一个成员函数。Members函数可以访问类的所有私有成员,无论您想访问相同或不同的对象,类都是相同的。如果您需要从类a.k.a之外访问它,您只需要一个getter。任何不是Matrix_成员的函数,谢谢。我不知道。但是我仍然想知道为什么我不能使用getData作为引用返回私有成员,而不能使用以下划线开头,后跟大写字母的标识符;这些是为实现保留的。别忘了把移动赋值也设为noexcept。一个类总是可以访问它自己的成员,不管他们是通过哪个对象访问的。我不知道,谢谢。但是为什么std::movem.getData不起作用。我不明白。所以如果我在课外使用getter函数。比如说。”std::unique_ptr c=std::make_unique100;c=std::movea.getData;'如何将数据移动到另一个智能指针因为m.getData是常量,通常不能从常量表达式移动。您需要一个非const且返回类型为std::unique\u ptr&或std::unique\u ptr&&的getter。这与其说是一个getter,不如说是一种提供数据的方法。
template <typename T>
Matrix<T>::Matrix(Matrix &&m) noexcept :
    rows_(m.rows_), cols_(m.cols_), size_(m.size_), data_(std::move(m.data_))
{
   // changes needed to m?
}

template <typename T>
Matrix<T>& Matrix<T>::operator=(Matrix &&m) noexcept
{
    rows_ = m.rows_;
    cols_ = m.cols_;
    size_ = m.size_;
    data_ = std::move(m.data_);
    // changes needed to m?
    return *this;
}