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.