編譯器默認的拷貝構造函數,發生的是Memberwise Initialization(成員逐一初始化),類的成員變量被逐一複製。而默認賦值運算符,也是逐一複製成員變量。
一旦成員變量中,有程序員在heap開闢的空間(指針,new),使用默認拷貝構造函數就會引起淺拷貝和深拷貝的問題。
淺拷貝:將指針指向的地址複製給新初始化的對象對應的成員變量,兩個類對象指向heap上的同一塊內存。一旦其中一個對象釋放那塊內存,另一個對象的指針就會變成野指針,對其進行操作可能會產生非常嚴重的錯誤。
深拷貝:對指針類型的成員變量,在堆區中重新開闢一塊內存,存儲的地址不同但是值相同。避免了淺拷貝的問題。
#include <iostream>
using namespace std;
class Matrix{
public:
Matrix(int row, int col):_row(row),_col(col)
{
_pmat = new double[row * col];
}
Matrix(const Matrix& rhs):_row(rhs._row),_col(rhs._col)
{
int elem_cnt = _row*_col;
_pmat = new double[elem_cnt];
for(int ix=0;ix<elem_cnt;++ix)
_pmat[ix] = rhs._pmat[ix];
}
Matrix& operator=(const Matrix &rhs);
~Matrix(){
delete[] _pmat;
}
private:
int _row, _col;
double * _pmat;
};
Matrix& Matrix::operator=(const Matrix& rhs){
if(this != &rhs){
_row = rhs._row;
_col = rhs._col;
int elem_cnt = _row * _col;
delete[] _pmat;
_pmat = new double[elem_cnt];
for(int ix=0;ix<elem_cnt;++ix)
_pmat[ix] = rhs._pmat[ix];
}
return *this;
}
與拷貝構造函數的初始化功能不同,調用重載的賦值運算符時,類本身已經被初始化過了。所以需要先確定兩個對象是否相同,然後刪除原先開闢的空間。