简体   繁体   中英

C++ - Matrix class copy constructor

I'm trying to set up a Matrix class and was wondering about the copy constructor. I have read through the copy-and-swap idiom and operator overloading . I can't decide which is more efficient:

Solution 1:

Matrix<T>::Matrix(const Matrix<T>& rhs) {
    Matrix<T> temp(rhs);
    this.swap(temp);
}

Matrix<T>::void swap(Matrix<T> rhs) 
: dx(rhs.dx), dy(rhs.dy) {
  allocArrays();
  for (int i=0; i<dx; ++i) {
    for (int j=0; j<dy; ++j) {
      p[i][j] = rhs.p[i][j];
    }
  }
}

or take the simple route and simply use

Solution 2:

Matrix::Matrix(const Matrix& rhs) 
: dx(m.dx), dy(m.dy) {
allocArrays();
  for (int i=0; i<dx; ++i) {
    for (int j=0; j<dy; ++j) {
      p[i][j] = rhs.p[i][j];
    }
  }
}

Matrix Header:

#ifndef MATRIX_H
#define MATRIX_H

#include <vector>

template <typename T> class Matrix {
private:
    std::vector<std::vector<T>> matrix;
    void allocArrays();  
    unsigned int dx, dy; // dimensions of x and y
    long **p; // pointer to pointer for long int

public:
    Matrix();
    ~Matrix();
    Matrix(const Matrix<T>& rhs);
    Matrix(unsigned xSize, unsigned ySize);
    Matrix<T>& operator=(const Matrix<T>& rhs);

    // Adding below code to showcase what else will be happening with the Matrices

    // Matrix mathematical operations                                                                                                                                                                                               
    Matrix<T> operator+(const Matrix<T>& rhs);
    Matrix<T>& operator+=(const Matrix<T>& rhs);
    Matrix<T> operator-(const Matrix<T>& rhs);
    Matrix<T>& operator-=(const Matrix<T>& rhs);
    Matrix<T> operator*(const Matrix<T>& rhs);
    Matrix<T>& operator*=(const Matrix<T>& rhs);
    Matrix<T> transpose();

    // Matrix/scalar operations                                                                                                                                                                                                     
    Matrix<T> operator+(const T& rhs);
    Matrix<T> operator-(const T& rhs);
    Matrix<T> operator*(const T& rhs);
    Matrix<T> operator/(const T& rhs);

    // Matrix/vector operations                                                                                                                                                                                                     
    std::vector<T> operator*(const std::vector<T>& rhs);
    std::vector<T> diag_vec();

    // Access the individual elements                                                                                                                                                                                               
    T& operator()(const unsigned& row, const unsigned& col);
    const T& operator()(const unsigned& row, const unsigned& col) const;
};

#include "matrix.cpp"
#endif

Matrix CPP file:

#ifndef _MATRIX_CPP
#define _MATRIX_CPP

#include "matrix.h"
#include <iostream>

// Default Constructor 
Matrix<T>::Matrix() : Matrix(1, 1) {}

// Parameter Constructor                                                                                                                                                      
template<typename T>
Matrix<T>::Matrix(unsigned xSize, unsigned ySize) 
    : dx(xSize), dy(ySize) {

    allocArrays();

    for (int i = 0; i < dx; i++) {
        for (int j = 0; j < dy; j++) {
            p[i][j] = 0;
        }
    }
}

// Copy Constructor @ which is most effective way of doing this                                                                                                                                                          
template<typename T>
Matrix<T>::Matrix(const Matrix<T>& rhs) {}

Matrix<T>::void allocArrays() {
    p = new long*[dx];
    for (int i = 0; i < dx; i++)
        p[i] = new long[dy];
}

The first solution implies a recursive constructor call and will never work :

Matrix<T>::Matrix(const Matrix<T>& rhs) {
    Matrix<T> temp(rhs);
        ^^^^^^^^^^^^^^
    // Recursive call here
    this.swap(temp);
}

As for any potential performance difference, always use a profiler on a decent set of test cases. If your swap is correctly implemented, you will see with any decent compiler that the creation of the temporary for the swap has a negligible cost compared to the allocation/filling of the matrix.

Note:

As your links show, the copy-and-swap idiom is implemented by the assignment operator (which calls the copy constructor), not the copy constructor itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM