我有一个用来实现矩阵的类,在这里:
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();
};
(对于这个特定的问题,向量不是一个选项。)
array_
成员保存矩阵本身,并使用以下代码填充:
array_ = new Comparable*[num_rows_];
for (int i = 0; i < num_rows_; ++i) {
array_[i] = new Comparable[num_cols_];
};
for(int i = 0;i < num_rows_; ++i) {
std::cout << "Enter items for row " << i << "." << std::endl;
for(int j = 0;j < num_cols_; ++j) {
std::cin >> array_[i][j];
}
}
我可以用值填充数组并访问它们,我的复制构造函数和移动赋值操作符是有效的,但是移动赋值操作符抛出了一个奇怪的错误。下面是定义
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::move(b);
为例。如果b的大小与a不同,则矩阵数据因移动而变形。如果b的列数多于a,多余的列数将被截断;如果b的行数少于a,则多余的行数将保留在a中;如果a比b有更多的列或行,那么多余的列将显示内存地址,而内存地址应该什么都没有。这是一个简单的bug吗?我创建数组的方式有问题吗?
"Move assign"并不意味着"小心地将传入的对象修改为某种'空'值",而是意味着"修改传入的对象是可以的"。
这里的Move赋值应该有一个非常简单的实现:只需交换。
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;
}
不确定为什么在移动赋值操作符中使用new Comparable*
。move分配的思想是移动资源,而不是制造新的资源。
你的代码可以像这样:
delete[] array_;
array_ = rhs.array_;
rhs.array_ = nullptr;
num_cols_ = rhs.num_cols_;
num_rows_ = rhs.num_rows_;
return *this;
但是,请考虑使用复制-交换习惯用法。这并不总是最有效的选择,但如果你不是大师,这是一个很好的起点。
注意:如果你真的想使用指针到指针来实现你的矩阵,使用vector<vector<Comparable>>
代替。所有的工作都为你完成了;你的代码只是在重新发明轮子。
通常用一个连续的分配来表示一个矩阵,而不是为每一行单独分配,这更简单、更有效,所以您可能需要考虑一下这个想法。