The Copy Constructor, operator=(), and Destructor
Learn about the importance of copy constructors and destructors, along with their implementation.
The matrix case study: Adding the copy constructor
Let’s implement the copy constructor using the deep copy for our Matrix
class. We’ll add a parameterized constructor that receives a Matrix
object as the parameter. Let’s add the signature in the Matrix.h
file.
Matrix(const Matrix& M);
Let’s add the definition in the Matrix.cpp
file.
Matrix::Matrix(const Matrix& M){this->Vs = nullptr;this->Allocate2D(M.rows,M.cols); // Allocates new memory for the matrix according to the given number of rows and columnsthis->copyValues(M); // Coppies the object in the newly allocated space}
Here, we can see that we allocate memory using the
Allocate2D()
function and copy the values usingcopyValues()
function in the newly allocated memory.
Overloading the assignment operator (=
)
Let’s overload the assignment operator (=
) by implementing the operator=()
function for the Matrix
class.
Matrix& Matrix::operator=(const Matrix& M){if (this == &M)return *this;if(this->Vs!=nullptr)this->DeleteMatrix();this->Allocate2D(M.rows, M.cols);this->copyValues(M);return *this;}
Why do we need a destructor in the Matrix
class?
The destructor is needed in this context to ensure proper cleanup and deallocation of resources held by a Matrix
object. In particular, the destructor is responsible for releasing dynamically allocated memory used by a Matrix
object, such as the memory for storing matrix elements and the memory for the row pointers. By defining a destructor, we can guarantee that the Matrix
object’s resources are properly released when it goes out of scope or is explicitly destroyed, preventing memory leaks and freeing system resources.
Matrix::~Matrix(){this->DeleteMatrix();}void Matrix::DeleteMatrix(){for (int i = 0; i < this->rows; i++)delete[]this->Vs[i];delete[]this->Vs;this->Vs = nullptr;this->rows = 0;this->cols = 0;}
The above code snippet shows the destructor
Matrix::~Matrix()
and the accompanying member functionMatrix::DeleteMatrix()
in theMatrix
class. The destructor is responsible for ensuring a proper cleanup of theMatrix
object. It calls theDeleteMatrix()
function, which iterates through each row of the matrix and deletes the dynamically allocated memory for the elements in that row. It then deletes the memory for the row pointers, sets the matrix pointer tonullptr
, and updates the number of rows and columns to0
, indicating an empty matrix. By callingDeleteMatrix()
in the destructor, theMatrix
object is effectively cleaned up, and any dynamically allocated memory is deallocated, preventing memory leaks and freeing system resources.
Complete basic implementation
Here’s the complete implementation of the copy constructor and overloading of the assignment (=
) operator.
3 3 4 7 5 9 8 5 3 7 2
This code snippet is a program that loads matrices from a file, makes a copy of the loaded matrices, and displays the original and copied matrices. The
LoadMatrix()
function reads the matrices from the file and stores them in a dynamically allocated array. In themain()
function, theLoadMatrix()
function is called to load the matrices. The pointerM2
is then assigned the value ofM1
to create a copy. Finally, the original and copied matrices are displayed.
Here’s the pictorial representation of the two matrices M1
and M2
(stored as arrays) in terms of memory.
Now that we have established the necessary foundation of loading matrices and understand copy constructors and the assignment operator, we can proceed to implement various operators on matrices. By doing so, we aim to create a comprehensive matrix calculator that can perform a wide range of operations.