第13章 复制控制

来源:互联网 发布:小草淘宝客 偷单 编辑:程序博客网 时间:2024/06/14 11:00

         复制构造函数、赋值操作符和析构函数总称为复制控制(copy control)。

13.1、复制构造函数

         复制构造函数可用于:(1)根据另一个同类型的对象显式或隐式初始化一个对象;(2)复制一个对象,将它作为实参传给一个函数;(3)从函数返回时复制一个对象;(4)初始化顺序容器中的元素,如vector<string> sev(5),分别用了默认构造函数和复制构造函数,先使用string默认构造函数创建一个临时值来初始化svec,然后用复制构造函数将临时值复制到svec的每个元素;(5)根据元素初始化式列表初始化数组元素(很多编译器都优化了,不会调用拷贝构造函数)。

         C++支持两种初始化形式:直接初始化(将初始化式放在圆括号中,用与实参匹配的构造函数)和复制初始化(用=号,调用拷贝构造函数)。

         对于如A a =string(“hello”);如果拷贝构造函数A(const string &)没有定义为explicit,则初始化成功

         当形参为非引用类型的时候,将复制实参的值;以非引用类型作返回值时,将返回return语句中的值的副本。

13.1.1、合成的复制构造函数

         如果我们没有定义复制构造函数,编译器就会为我们合成一个(行为是逐个成员(非static)初始化)。

13.1.2、定义自己的复制构造函数

         复制构造函数就是接受单个类类型引用形参(通常用const修饰,如A(const A&))的构造函数。

13.1.3禁止复制

         为了防止复制,类必须显示声明其复制构造函数为private。如果要是友元和成员中也禁止,则可以声明但不定义。用户代码中的复制尝试将在编译时标记为错误,而成员函数和友元中的复制尝试将在链接时导致错误

13.2、赋值操作符

         重载操作符,形参表必须具有与该操作符操作数数目相同的形参。

         当操作符成为成员函数时,它的第一个操作数隐式绑定到this指针。因此赋值操作符接受单个形参,且该形参是同一类类型的对象,右操作数一般为const引用传递。如A& operator=(const A &);

         合成赋值操作符根据成员类型使用适合的内置或类定义的赋值操作符,依次给每个成员赋值,该操作符返回*this,它是对左操作数对象的引用

13.3、析构函数

         动态分配的对象只有在指向该对象的指针被删除时才撤销,没有删除会导致内存泄露。

         容器中的元素总是按逆序撤销。即首先撤销下标最大的,依次往前。

         三法则:如果类需要析构函数,则它也需要赋值操作符和复制构造函数。析构函数常用于释放在构造函数或在对象生命周期内获取的资源

         编译器总是会为我们合成一个析构函数,它按对象创建时的逆序撤销每个非static成员(即它按成员在类中声明次序的逆序撤销成员,它不会删除指针成员所指向的对象,因此需要显示delete)。

         编写了自己的析构函数,合成析构函数仍然运行

13.5、管理指针对象

         一般的默认复制对象是浅拷贝,因此对于类中有指针的,复制后,两个对象指向同一个指针。因此会导致删除了一个对象的指针,另一个对象的指针成员悬垂指针。

13.5.1、定义智能指针

         智能指针一般使用“计数”,引用计数。单独定义一个计数类(该类保存对应类所需的指针(因此某个对应类如果改变指针指向,则所有指向该计数类的对应类指针指向都变了)和计数值,将要计数的类设为其友元,对应的类中将该计数类设为成员)。赋值操作先计数器加1再减少,防止自身赋值操作。

         为了管理具有指针成员的类,必须定义三个复制控制成员:复制构造函数赋值操作符析构函数

13.5.2、定义值型类

         处理指针成员,还可以深拷贝。