Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ “如何改进”=&引用;矩阵的算子重载?_C++ - Fatal编程技术网

C++ “如何改进”=&引用;矩阵的算子重载?

C++ “如何改进”=&引用;矩阵的算子重载?,c++,C++,我为具有2D数组的类重载了赋值运算符,但为了进行内存管理和正确调整大小,我必须先删除以前的矩阵,然后构造一个新矩阵,然后才能开始赋值 矩阵和矩阵::运算符=(常数矩阵和m1){ 对于(int i=0;i

我为具有2D数组的类重载了赋值运算符,但为了进行内存管理和正确调整大小,我必须先删除以前的矩阵,然后构造一个新矩阵,然后才能开始赋值

矩阵和矩阵::运算符=(常数矩阵和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
    进行矩阵存储,则根本不需要实现复制/移动构造函数/赋值和析构函数

    如果您正在做的是一个编程练习,那么创建您自己的动态