对copy-constructor的一点理解

Memberwise Initialization

在默认情况下,当以某个class object作为另一个object的初值时,会发生成员逐一初始化,

1
2
Example E1(8);
Example E2 = E1;

class data member会被依次复制,即对象中的每个成员都会被复制到另一个对象的相应成员上。

对于这种情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Matrix {
public:
Matrix(int row, int col) : _row(row), _col(col)
{
_pmat = new double[row * col];
}
~Matrix()
{
delete [] _pmat;
}
private:
int _row, _col;
double *_pmat;
};


// in this case

Matrix mat(4, 4);
//此处constructor发生作用
{
Matrix mat2 = mat;
// 此处进行了default memberwise initialization
// ...
// 此处,mat2的destructor发生作用。
}

根据默认的成员逐一初始化,mat2._pmat = mat._pmat,所以这两个指针指向了同一个堆内存空间内的数组,当mat2的析构函数发生作用时,该内存空间便被释放,但是mat的指针还是指同一空间,此时再使用这个指针就会产生严重错误。

解决方法:copy constructor

为了改变这种默认的成员逐一初始化的行为模式,可以为这个类提供一个拷贝构造函数。

拷贝构造函数其唯一参数是一个 “const reference”

1
2
3
4
5
6
7
8
Matrix::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];
}

设计类时需要考虑默认的行为模式是否合适?如果不合适就需要另行定义copy constructor。

同时,如果有必要为某个class编写copy constructor,那么同样有必要为它编写copy assignment operator。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
}
作者

Jhuoer Yen

发布于

2022-01-30

更新于

2023-09-18

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×