C++ Primer 复制控制

来源:互联网 发布:python php 开发效率 编辑:程序博客网 时间:2024/05/17 03:59

复制控制:

当定义一个新类型的时候,需要显式或隐式地指定复制、赋值和撤销该类型的对象时会发生什么——这是通过定义特殊成员:复制构造函数、赋值操作符和析构函数来达到的。如果没有显式定义复制构造函数或赋值操作符,编译器(通常)会为我们定义。

 

复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数。

析构函数是构造函数的互补:当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都自动执行类中非static 数据成员的析构函数

实现复制控制操作最困难的部分,往往在于识别何时需要覆盖默认版本。有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员

复制构造函数可用于:

根据另一个同类型的对象显式或隐式初始化一个对象。

 复制一个对象,将它作为实参传给一个函数。

 从函数返回时复制一个对象。

 初始化顺序容器中的元素。

 根据元素初始化式列表初始化数组元素。

复制初始化使用 =符号,而直接初始化将初始化式放在圆括号中。

如果使用常规的花括号括住的数组初始化列表(第 4.1.1节)来提供显式元素初始化式,则使用复制初始化来初始化每个元素

Sales_item primer_eds[] = { string("0-201-16487-6"),

                                string("0-201-54848-8"),

                                string("0-201-82470-1"),

                                Sales_item()

                              };

禁止复制:

有些类需要完全禁止复制。例如,iostream类就不允许复制(第 8.1节)。如果想要禁止复制,似乎可以省略复制构造函数,然而,如果不定义复制构造函数,编译器将合成一个。为了防止复制,类必须显式声明其复制构造函数为 private

如果复制构造函数是私有的,将不允许用户代码复制该类类型的对象,编译器将拒绝任何进行复制的尝试。然而,类的友元和成员仍可以进行复制。如果想要连友元和成员中的复制也

禁止,就可以声明一个(private)复制构造函数但不对其定义。声明而不定义成员函数是合法的。

合成赋值操作符与合成复制构造函数的操作类似。它会执行逐个成员赋值:右操作数对象的每个成员赋值给左操作数对象的对应成员。除数组之外,每个成员用所属类型的常规方式进行赋值。对于数组,给每个数组元素赋值。

例如,Sales_item的合成赋值操作符可能如下所示:

    // equivalent to the synthesized assignment operator

    Sales_item&

    Sales_item::operator=(const Sales_item &rhs)

    {

        isbn = rhs.isbn;              // calls string::operator=

        units_sold = rhs.units_sold;  // uses built-in int assignment

        revenue = rhs.revenue;        // uses built-in double

assignment

        return *this;

    }

动态分配的对象只有在指向该对象的指针被删除时才撤销。如果没有删除指向动态对象的指针,则不会运行该对象的析构函数,对象就一直存在,从而导致内存泄漏,而且,对象内部使用的任何资源也不会释放。当对象的引用或指针超出作用域时,不会运行析构函数。只有

删除指向动态分配对象的指针或实际对象(而不是对象的引用)

超出作用域时,才会运行析构函数。

何时编写显式析构函数

仅在有些工作需要析构函数完成时,才需要析构函数。析构函数通常用于释放在构造函数或在对象生命期内获取的资源。如果类需要析构函数,则它也需要赋值操作符和复制构造函

数,这是一个有用的经验法则。这个规则常称为三法则,指的是如果需要析构函数,则需要所有这三个复制控制成员。

合成析构函数按对象创建时的逆序撤销每个非 static成员,因此,它按成员在类中声明次序的逆序撤销成员。

析构函数与复制构造函数或赋值操作符之间的一个重要区别是,即使我们编写了自己的析构函数,合成析构函数仍然运行。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 老人吃了就吐怎么办 老人吃饭噎着了怎么办 胃胀气嗝不出来怎么办 嗓子咽口水都疼怎么办 产后盆底肌肉松弛怎么办 2个月宝宝鼻塞怎么办 人淹死捞不上来怎么办 胶囊卡在胃里怎么办 药卡在气管里怎么办 胶囊药卡在气管怎么办 被胶囊卡在喉咙怎么办 药卡在食道里怎么办 胶囊黏在喉咙里怎么办 要一直卡在喉咙怎么办 胃老是往上反气怎么办 有口气憋在喉咙怎么办 肛裂伤口不愈合怎么办 肛裂口子不愈合怎么办 宝宝胃食道反流怎么办 去角质后脸发红怎么办 红烧肉做的太甜怎么办 红烧排骨太甜了怎么办 唱歌时嗓子有痰怎么办 一唱歌喉咙有痰怎么办 鼻子老是打喷嚏还流鼻涕怎么办 鼻涕流到喉咙里怎么办 鼻塞怎么办怎样让鼻通气 流清鼻涕嗓子疼怎么办 喉咙疼咳嗽有痰怎么办 扁桃体发炎痛得厉害怎么办 腭垂掉下来了怎么办 喉咙干有异物感怎么办 嗓子干有异物感怎么办 输液的时候手疼怎么办 一感冒就嗓子哑怎么办 4岁儿童喉咙沙哑怎么办 嗓子老有异物感怎么办 喉咙咽口水都疼怎么办? 舌头上长了溃疡怎么办 包包的拉链坏了怎么办 做试管取精困难怎么办