软件设计 2017-03-30
每一次都会忘,做个笔记吧。想到哪里写到哪里。
拷贝初始化:要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话,还要进行类型转换。
string dots(10, '.'); //直接初始化 string s(dots); //直接初始化 string s2 = dots; //拷贝初始化 string null_book = "9-999-8999"; //拷贝初始化 string nines = string(100, '9'); //拷贝初始化使用‘=’号的是拷贝初始化,不使用等号的是直接初始化。
拷贝初始化发生在以下情况
1. 用 = 定义变量时发生。 2. 将一个对象作为实参传递给一个非引用类型的形参。 3. 从一个返回类型为非引用类型的函数返回一个对象。 4. 用花括号列表初始化一个数组中的元素或一个聚合类中的成员。(聚合类是指没有用户定义的构造函数,没有私有和保护的非静态数据成员,没有基类,没有虚函数)。拷贝构造函数第一个参数必须是引用原因:由于拷贝构造函数被用来初始化非引用类类型的参数。如果其自身参数不是引用类型,则调用永远也不会成功——为了调用拷贝构造函数,我们必须拷贝它的实参,但为了拷贝实参,我们又必须调用拷贝构造函数,如此无限循环。
与类控制其对象如何初始化一样,类也可以控制器对象如何赋值:
Sales_data trans, accum; trans = accum; //使用Sales_data的拷贝赋值运算符与拷贝构造函数一样,如果类未定义自己的拷贝赋值运算符,编译器也会为它合成一个。 重载赋值运算符 重载运算符本质上是函数,其名字由operator关键字后接表示要定义的运算符的符号组成。因此,赋值运算符就是一个名为operator=的函数。类似于任何其他函数,运算符函数也有一个返回类型和一个参数列表。 如果是一个运算符是一个成员函数,其左侧运算对象就绑定到隐式的this参数。对于一个二元运算符,例如赋值运算符,其右侧运算对象作为显式参数传递。
拷贝赋值运算符接受一个与其类相同类型的参数:
class Foo{ public: Foo& operator=(const Foo&); //赋值运算符 //... };
为了与内置类型的赋值保持一致,赋值运算符通常返回一个指向其左侧运算对象的引用。注意,标准库通常要求保存在容器中的类型要有其赋值运算符,且其返回值是左侧运算对象的引用。
析构函是类的一个成员函数,名字由波浪号接类名构成。它没有返回值,也不接受参数:
class Foo{ public: ~Foo(); //析构函数 //... };由于析构函数不接受参数,因此它不能被重载。对于一个给定类,只会由唯一一个析构函数。 在一个构造函数中,成员的初始化时在函数体执行之前完成的,且按照它们在类中出现的顺序进行初始化。在一个析构函数中,首先执行函数体,然后销毁成员。成员按初始化顺序的逆序进行销毁。
无论何时一个对象被销毁,就会自动调用其析构函数:
1. 变量在离开其作用域时被销毁 2. 当一个对象被销毁时,其成员被销毁 3. 容器(无论是标准容器还是数组)被销毁时,其元素被销毁 4. 对于动态分配的对象,当对指向它的指针应用delete运算符时被销毁 5. 对于临时对象,当创建它的完整表达式结束时被销毁