C++ “如何改进”=&引用;矩阵的算子重载?
我为具有2D数组的类重载了赋值运算符,但为了进行内存管理和正确调整大小,我必须先删除以前的矩阵,然后构造一个新矩阵,然后才能开始赋值C++ “如何改进”=&引用;矩阵的算子重载?,c++,C++,我为具有2D数组的类重载了赋值运算符,但为了进行内存管理和正确调整大小,我必须先删除以前的矩阵,然后构造一个新矩阵,然后才能开始赋值 矩阵和矩阵::运算符=(常数矩阵和m1){ 对于(int i=0;i
矩阵和矩阵::运算符=(常数矩阵和m1){
对于(int i=0;i
事实上,这部分是我的类的析构函数:
for(int i=0;i
这部分类似于构造器:
m_matrix=new double*[m1.rows()];
对于(int i=0;i
让我恼火的是,我必须在赋值函数(以及其他一些函数)中复制构造函数和析构函数的代码,以使其正常工作。有更好的编写方法吗?赋值运算符的规范化实现利用了现有功能(复制/移动ctor、dtor和
swap()
;请注意,使用非专用的std::swap()
将是不好的)。看起来是这样的:
T& T::operator= (T val) {
val.swap(*this);
return *this;
}
它很好地避免了重新实现现有的逻辑。它还优雅地处理了原始代码中的自分配问题(它可以工作,但自分配通常相当少见;通过检查自分配来优化它通常会使代码悲观)
参数按值传递以利用复制省略
这种方法的主要注意事项如下。一般来说,我更喜欢规范化的实现,因为它通常更正确,并且概述的问题通常不是那么相关(例如,当对象刚刚创建时,传输的内存实际上是“热的”)
赋值运算符的规范化实现利用了现有功能(复制/移动ctor、dtor和
swap()
;请注意,使用非专用的std::swap()
将是不好的)。看起来是这样的:
T& T::operator= (T val) {
val.swap(*this);
return *this;
}
它很好地避免了重新实现现有的逻辑。它还优雅地处理了原始代码中的自分配问题(它可以工作,但自分配通常相当少见;通过检查自分配来优化它通常会使代码悲观)
参数按值传递以利用复制省略
这种方法的主要注意事项如下。一般来说,我更喜欢规范化的实现,因为它通常更正确,并且概述的问题通常不是那么相关(例如,当对象刚刚创建时,传输的内存实际上是“热的”)
理想的改进是
Matrix&Matrix::operator=(const-Matrix&)=default代码>
如果切换到使用std::vector
进行矩阵存储,则根本不需要实现复制/移动构造函数/赋值和析构函数
如果您正在做的是一个编程练习,那么创建您自己的动态数组,并在矩阵的实现中使用它
我不能推荐足够的关注,他有效地演示了为什么您应该努力编写不需要复制/移动构造函数/赋值和析构函数的非默认实现的类
例如:
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;
};
模板
类矩阵
{
std::向量存储;
无符号列=0;
公众:
矩阵(无符号行、无符号列)
:存储(行*列)
,cols_(cols)
{}
//因为上面的用户定义构造函数
//必须提供默认构造函数。
//默认实现就足够了。
矩阵()=默认值;
无符号列()常量{return cols_;}
无符号行()常量{return storage_uz.size()/cols_z;}
//使用运算符()进行索引,因为[]只能接受一个参数。
运算符()(无符号行,无符号列){return storage_u[row*cols_u+col];}
T const&operator()(无符号行,无符号列)const{return storage.[uurow*cols.+col];}
//规范交换成员函数。
无效掉期(矩阵和b){
使用std::swap;
交换(存储,b.存储);
交换(cols_uux,b.cols_ux);
}
//规范交换函数。朋友名注入。
朋友无效交换(矩阵&a,矩阵&b){a.swap(b);}
//这就是编译器为您所做的,
//根本不需要申报这些。
矩阵(矩阵常数&)=默认值;
矩阵(矩阵&&)=默认值;
矩阵和运算符=(矩阵常数&)=默认值;
矩阵和运算符=(矩阵和运算符)=默认值;
~Matrix()=默认值;
};
理想的改进是矩阵和矩阵::运算符=(常数矩阵和)=默认值代码>
如果切换到使用std::vector
进行矩阵存储,则根本不需要实现复制/移动构造函数/赋值和析构函数
如果您正在做的是一个编程练习,那么创建您自己的动态