以拷贝的方式初始化对象

初始化对象时会调用构造函数,不同的初始化方式会调用不同的构造函数:

  • 如果用传递进来的实参初始化对象,那么会调用普通的构造函数,我们不妨将此称为普通初始化;
  • 如果用其它对象(现有对象)的数据来初始化对象,那么会调用拷贝构造函数,这就是以拷贝的方式初始化。

对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。但是当类持有其它资源时,例如动态分配的内存、指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据。


这种将对象所持有的其它资源一并拷贝的行为叫做深拷贝,我们必须显式地定义拷贝构造函数才能达到深拷贝的目的。

重载=运算符

Array &Array::operator=(const Array &arr){  //重载赋值运算符
    if( this != &arr){  //判断是否是给自己赋值
        this->m_len = arr.m_len;
        free(this->m_p);  //释放原来的内存
        this->m_p = (int*)calloc( this->m_len, sizeof(int) );
        memcpy( this->m_p, arr.m_p, m_len * sizeof(int) );
    }
    return *this;
}

关于为什么要返回*this:

解释如下:

为了编程的简洁性,有时候需要串联赋值,如:x = y = z = 15; 由于赋值采用右结合,因此上述语句被解释为:x = (y = (z = 15));

为了实现串联赋值,复制操作符函数必须返回一个指向操作符左侧实参的的引用,如下:

 1 class Widget
 2 {
 3 public:
 4     ...
 5     Widget& operator=(const Widget& rhs)
 6     {
 7     ...
 8     return *this;
 9     }
10     ...
11 };

注意:

这个规则不仅适用于赋值 = ,对于其他操作符如 += 、 -= 等同样适用。

当定义一个类时,我们显式地或隐式地指定了此类型的对象在拷贝、赋值和销毁时做什么。一个类通过定义三种特殊的成员函数来控制这些操作,分别是拷贝构造函数赋值运算符析构函数

02-10 16:37