赋值操作符的定义:
1)赋值操作符,就是常用变量赋值的“=”,将一个玩意赋值给另一个玩意
2)默认形式:classType & operator=(const classType &);
operator后面紧跟要重载的操作符就是操作符重载的默认形式;形参是本类类型的引用,默认第一个形参就是类类型对象自己的指针this;返回类型就是类类型的引用
合成赋值操作符:
合成赋值操作符也是采用逐个成员初始化,右操作对象的每个成员赋值给左操作数对象的对应成员。数组仍然是给每个元素赋值。
使用场景:
可以使用合成复制构造函数的地方通常也可以使用合成赋值操作符。一般而言,如果需要定义复制构造函数,通常也需要定义赋值操作符。如下一个赋值操作函数的例子:
class Employee
{
public:
Employee(); //默认构函数
~ Employee();//析构函数
Employee(const string & name); //带有一个形参的构造函数
Employee(const Employee & employ); //复制构造函数
Employee& operator=(const Employee& employ); //赋值操作符
private:
string name;
string ID;
public:
string GetName() const;
string GetID() const;
string SetID(void);
int SetName(const string&);
};
//赋值函数
Employee& Employee::operator=(const Employee& employ)
{
name = employ.name;
ID = employ.ID;
return *this;
}
析构函数定义:
1)析构函数就是要释放构造分配的资源,就是进行资源的回收。
2)析构函数原型: ~classType();
3)析构函数无返回值,也无任何形参。
4)析构函数不能被重载
何时调用析构函数:
撤销类对象时会自动调用析构函数,动态分配的对象只有在指向该对象的指针被删除时才撤销,因为动态分配的空间存在与用户自由使用的堆空间。如果没有删除指向动态对象的指针,则不会运行该对象的析构函数,对象就会一直存在,从而导致内存泄露,而且对象内部的任何资源也不会释放。如下:
sales_item *p = new sales_item;
{
sales_item item(*p); //调用复制构造函数传递参数,然后直接创建类对象
delete p;
}
delete p;执行后就调用析构函数删除p,而item是在超出作用域后才被调用就是最后一个},因为item是栈上分配的空间,所以当所处的位置生命期终结,也就会自动调用析构函数。
总结一下就是:只有删除指向动态分配对象的指针或者实际对象超出作用域,才会运行析构函数,注意这里的实际对象不是对象的引用.
何时编写析构函数
通常不一定需要自己的析构函数,如果类需要析构函数来专门释放资源的话,那么赋值操作符和复制构造函数也是必须的,这就是所谓的三法则。
合成析构函数
1)编译器总为我们合成一个析构函数,即使我们自己编写自己的析构函数。
2)合成析构函数按对象创建时的逆序撤销每个非static成员。
3)合成析构函数并不删除指针成员所指向的对象。
4)当我们编写了什么也不做的析构函数,它执行完毕后也会执行合成析构函数,用来撤销类的成员。