![](/img/trans.png)
[英]operator overloading in matrices: how to overload () and = at the same time
[英]How to improve “=” operator overload for matrices?
我為帶有2D數組的類重載了賦值運算符,但是為了進行內存管理和正確調整大小,我必須先刪除先前的矩陣,然后構造一個新的矩陣,然后才可以開始賦值。
Matrix& Matrix::operator = (const Matrix& m1){
for (int i = 0; i < m_rows; ++i)
delete[] m_matrix[i];
delete[] m_matrix;
m_matrix = new double*[m1.rows()];
for (int i = 0; i < m1.rows(); ++i)
m_matrix[i] = new double[m1.cols()]();
for (int k = 0; k < m1.rows(); ++k)
for (int j = 0; j < m1.cols(); ++j)
m_matrix[k][j] = m1.m_matrix[k][j];
m_rows = m1.rows();
m_cols = m1.cols();
return *this;
}
實際上,這部分是我的課堂的破壞者:
for (int i = 0; i < m_rows; ++i)
delete[] m_matrix[i];
delete[] m_matrix;
這部分類似於構造函數:
m_matrix = new double*[m1.rows()];
for (int i = 0; i < m_rows; ++i)
m_matrix[i] = new double[m1.cols()]();
讓我煩惱的是,我必須在賦值函數(以及其他一些函數!)中復制構造函數和析構函數的代碼,以使其正常工作。 有更好的書寫方式嗎?
理想的改進是Matrix& Matrix::operator=(const Matrix&) = default;
。
如果切換到使用std::vector
進行矩陣存儲,則根本不需要實現復制/移動構造函數/賦值和析構函數。
如果您正在做的是編程練習,請創建自己的動態數組,並將其用於矩陣的實現中。
我不能推薦觀看Sean Parent的《更好的代碼:運行時多態》 ,這有效地說明了為什么您應該努力編寫不需要復制/移動構造函數/賦值和析構函數的非默認實現的類。
例:
template<class T>
class Matrix
{
std::vector<T> storage_;
unsigned cols_ = 0;
public:
Matrix(unsigned rows, unsigned cols)
: storage_(rows * cols)
, cols_(cols)
{}
// Because of the user-defined constructor above
// the default constructor must be provided.
// The default implementation is sufficient.
Matrix() = default;
unsigned columns() const { return cols_; }
unsigned rows() const { return storage_.size() / cols_; }
// Using operator() for indexing because [] can only take one argument.
T& operator()(unsigned row, unsigned col) { return storage_[row * cols_ + col]; }
T const& operator()(unsigned row, unsigned col) const { return storage_[row * cols_ + col]; }
// Canonical swap member function.
void swap(Matrix& b) {
using std::swap;
swap(storage_, b.storage_);
swap(cols_, b.cols_);
}
// Canonical swap function. Friend name injection.
friend void swap(Matrix& a, Matrix& b) { a.swap(b); }
// This is what the compiler does for you,
// not necessary to declare these at all.
Matrix(Matrix const&) = default;
Matrix(Matrix&&) = default;
Matrix& operator=(Matrix const&) = default;
Matrix& operator=(Matrix&&) = default;
~Matrix() = default;
};
賦值運算符的規范實現利用了現有功能(復制/移動ctor,dtor和swap()
;請注意,使用非專用的std::swap()
會很不好)。 看起來像這樣:
T& T::operator= (T val) {
val.swap(*this);
return *this;
}
很好地避免了重新實現現有的邏輯。 它還可以很好地處理自我分配問題,這在您的原始代碼中是個問題(它可以正常工作,但自我分配通常並不常見;通過檢查自我分配來對其進行優化通常會悲觀代碼)。
該參數按值傳遞以利用復制省略。
下面是使用此方法的主要注意事項。 總的來說,我更喜歡規范的實現,因為它通常更正確,而且所概述的問題通常並不那么相關(例如,無論何時剛創建對象時,傳輸的內存實際上都是“熱”的)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.