[英]How I can implement move constructor and operator for unique_ptr as a private member of class
我正在嘗試編寫Matrix類。 我使用unique_ptr作為存儲指針數組。 但是這個 unique_ptr 是類的私有成員。 我想向我的 Matrix 類添加移動構造函數。 但是我需要私有unique_ptr 的getter函數,但是當我將 unique_ptr 作為 const 變量返回時,我不能使用 std::move 但是當我返回沒有 const 引用的 getter 函數時,編譯器不允許這樣做。
矩陣.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_()
{
}
測試文件
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;
}
錯誤
error: use of deleted function ‘std::unique_ptr<_Tp [], _Dp>& std::unique_ptr<_Tp [], _Dp>::operator=(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = double; _Dp = std::default_delete<double []>]’
data_ = std::move(_m.getData());
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/7/bits/locale_conv.h:41:0,
from /usr/include/c++/7/locale:43,
from /usr/include/c++/7/iomanip:43,
from /home/cemo/YZlib/Examples/Test.cpp:3:
/usr/include/c++/7/bits/unique_ptr.h:654:19: note: declared here
unique_ptr& operator=(const unique_ptr&) = delete;
不要在移動構造函數或移動賦值中使用 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;
}
一個類總是可以訪問它自己的成員(無論它們是通過哪個對象訪問的)。
一定要考慮現在m
會發生什么,因為它的data_
是一個空指針。 它的rows_
、 cols_
和size_
應該設置為零,還是無關緊要? 通常,移動的對象應該處於“有效但未指定”狀態,無論您決定對您的類意味着什么。 至少,調用析構函數應該是有效的,並且將它分配給其他東西應該按預期工作; 這些已經是這樣了。
由於這里不需要 getter,因此公共接口是否應該包含一個 getter,或者它是否應該有一個更方便的返回類型,比如const T*
或T*
,這是一個單獨的問題。
正在做:
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函數,只有當你想訪問類外的成員時才需要。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.