第13章:复制控制
——复制构造函数、赋值操作符和析构函数总称为复制控制(copy control)。
——有一种特别常见的情况需要类定义自己的复制控成员的:类具有指针成员。Good !
第一节:复制构造函数
——只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为复制构造函数。
——复制构造函数可由编译器隐式调用。
@学习摘录148:复制构造函数与默认构造函数
——一般来说,最好显式或隐式定义默认构造函数和复制构造函数。
——只有不存在其他构造函数时才合成默认构造函数。
——如果定义了复制构造函数,也必须定义默认构造函数。Ok !
@学习摘录149:初始化的复制形式和直接形式
——直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。
——复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。
——有些类的构造函数定义为explicit。如果构造函数是显式的,则初始化失败;如果构造函数不是显式的,则初始化成功。
——class Foo { Foo(const Foo&); // copy constructor };
@学习摘录150:合成的复制构造函数
——如果我们没有定义复制构造函数,编译器会为我们合成默认复制构造函数(synthesized copy constructor)。
——即使我们定义了其他构造函数,也会合成复制构造函数。
@学习摘录151:逐个成员初始化(memberwise initialize)
——合成复制构造函数执行逐个成员初始化,将新对象初始化为原对象的副本。
——逐个成员初始化最简单的概念模型是,将合成复制构造函数看作每个数据成员在构造函数初始化列表中进行初始化。
@学习摘录152:禁止复制
——有些类需要完全禁止复制,为了防止复制,类必须显式声明其复制构造函数为private。
——如果复制构造函数是私有的,将不允许用户代码复制该类类型的对象,编译器将拒绝任何进行复制的尝试。
——当声明一个(private)复制函数但不对其定义时,可以连友元和成员中的复制也禁止。Good !
——声明而不定义成员函数是合法的,但是,使用未定义成员的任何尝试将导致链接失败。
第二节:赋值操作符
@学习摘录153:赋值操作符的定义
——赋值操作符的返回类型应该与内置类型赋值运算返回的类型相同。
——class Sales_item{ Sales_item& operator = (const Sales_item & ); };
@学习摘录154:合成赋值操作符
——合成赋值操作符会执行逐个成员赋值:右操作数对的每个成员赋值给左操作数对象的对应成员。
——除数组之外,每个成员用所属类型的常规方式进行赋值。对于数组,给每个数组元素赋值。
第三节:析构函数
——析构函数通常用于释放在构造函数或在对象生命期内获取的资源。
@学习摘录155:何时编写显式析构函数
——如果类需要析构函数,则它也需要赋值操作符和复制构造函数,这是一个有用的经验法则,称为三法则(rule of three)。 GOOD !
@学习摘录156:合成析构函数
――与复制构造函数或赋值操作符不同,编译器总会为我们合成一个析构函数。
——析构函数与复制函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合成析构函数仍然运行。
——合成析构函数按对象创建时的逆序撤销每个非static成员,因此,它按成员在类中声明次序的逆序撤消成员。
第五节:管理指针成员
——包含指针的类需要特别注意复制控制,原因是复制指针时只复制指针中的地址,而不会复制指针指向的对象。
@学习摘录157:管理指针成员的方法
——1. 指针成员采取常规指针型行为。 这样的类具有指针的所有缺陷但无需特殊的复制控制。
——2. 类可以实现所谓的“智能指针”行为。指针所指向的对象是共享的,但类能够防止悬垂指针。(悬垂指针主要使用的是使用计数技术)
——3. 类采取值型行为。指针所指向的对象是唯一的,由每个类对象独立管理。
摘录有想157:
——之前一直对智能指针不怎么懂,今天,再次看了几个例子以后,自己打了一次代码以后,发觉,原来,这个智能指针也没有想像中的复杂,只是多了一个计数的功能。
@学习摘录158:智能指针
——一个行为类似指针但也提供其他功能的类。
——智能指针的一个通用形式接受指向动态分配对象的指针并负责删除该对象。
——用户分配对象,但由智能指针删除它。
——智能指针类需要实现复制控制成员来管理指向共享对象的指针。
——只有在撤消了指向共享对象的最后一个智能指针后,才能删除该共享对象。
——使用计数是实现智能指针类的最常用的方式。