动态内存分配与特殊成员函数
当类成员中不使用new时,不论是在继承关系中还是非继承关系中,一般都可以依赖自动生成的特殊成员函数进行初始化、赋值等操作。
但当类成员中使用new初始化时情况变得复杂:
一、非继承关系时
1.用类对象初始化类对象,应自定义复制构造函数并在其中添加new以进行深度复制,还应该自定义显式析构函数并在其中添加delete释放指针空间。
2.用类对象给类对象赋值,应重载赋值运算符:在其中先判断实参与*this是否相同,然后使用delete释放指针空间,再使用new动态分配新空间给指针并赋值,最后return *this。
二、 继承关系时(主要看派生类)
首先说明:基类的特殊成员函数与非继承关系时的情况雷同,重点在于派生类。
1.派生类不用new的情况(即使基类中有使用new的成员):
同样可以依赖自动生成的特殊成员函数进行初始化、赋值等操作。
因为派生类的默认构造函数、析构函数以及赋值运算符会自动调用基类的构造函数、析构函数和赋值运算符以完成派生类中基类部分的初始化和清除。
2.派生类有使用new进行初始化的成员的情况:
此种情况下必须为派生类定义显式析构函数、复制构造函数和赋值运算符;
- 定义派生类析构函数:
应添加delete删除派生类中新增的指针。至于基类部分中的指针,派生类析构函数会自动调用基类的析构函数删除。(当然前提条件是你已经在基类的析构中加入delete了)。简单来讲,就是各管各的,基类析构管基类new,派生类只管派生类new; - 定义派生类复制构造函数:
应在函数体前加入基类复制构造函数用于复制基类部分,并在函数体中添加new;即用初始化列表的方式加入基类复制构造函数(由于引用兼容性,其参数为派生类)。 - 定义派生类赋值运算符:
增加用函数表示法显式调用基类赋值运算符的语句:如:base:: operator=(derive);用来赋值派生类derive的基类部分base。
cpp primer plus中的解释:
另外,还有一个问题:
虚析构函数何时出现:
当一个基类指针指向用new运算符动态生成的派生类对象时,若想用delete释放此指针,应在基类中显式地定义一个虚析构函数才能完成,否则会造成内存泄漏。
作为初学者,个人感觉以上所述是cpp中最混乱,最令人困惑的地方之一。