您的位置:首页 > 编程语言 > C语言/C++

《C++primer》读书笔记二

2016-04-16 08:34 525 查看
13章.复制控制
复制构造函数。赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。
需要定义自己的复制控制成员的:类具有指针成员。
13.1复制构造函数(拷贝构造):只有单个形参,而且该形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为复制构造函数。
复制构造函数可用于:
1.根据另一个同类型的对象显示或隐式初始化一个对象
2.复制一个对象,将它作为实参传递给一个函数
3.从函数返回复制一个对象。
4.初始化顺序容器中的元素
5.根据元素初始化式列表初始化数组元素
直接初始化直接调用与实参匹配的构造函数,赋值初始化总是调用复制构造函数,首先创建一个临时对象,然后用复制狗凹函数将那个临时对象复制到正在创建的对象。
13.1.1合成的复制构造函数
合成复制构造函数的行为是:执行逐个成员初始化,将新对象初始化为原对象的副本。
13.1.3禁止复制:为了防止复制,类必须显示声明其复制构造函数为private.(只声明,不定义)
13.2赋值操作符:操作符函数有一个返回值和一个形参表。形参表必须具有与该操作符操作数数目相同的形参。赋值是二元运算,所以操作符函数有两个形参:第一个形参对应左操作数,第二个形参对应右操作数。 操作符返回对同一类类型的引用。
3.复制和赋值常一起使用:应将这两个操作符看做一个单元,如果需要其中一个,另一个也基本需要
13.3析构函数
何时调用析构函数:
1.撤销类对象时会自动调用析构函数
注:当对象的引用或指针超出作用域时,不会运行析构函数,只有删除指向动态分配对象的指针或实际对象(而不是对象的引用)超出作用域是,才会运行析构函数。
2.撤销一个容器(不管是标准库容器还是内置数组)时,也会运行容器中的类类型元素的析构函数。
4.如何编写析构函数
1.析构函数只有一个

13.5管理指针成员:
大多数C++类采用以下三种方法管理指针成员:
1.指针成员采用常规指针型行为,这样的类具有指针的所有缺陷但无需特殊的复制控制。
2.类可以实现所谓的智能指针,指针所指向的对象是共享的,但类能够防止悬垂指针
3.类采取值型行为。指针所指向的对象时唯一的,有每个类对象独立管理。

具有指针成员且使用默认合成复制构造函数的类具有普通指针的所有缺陷,尤其是,类本身无法避免悬垂指针
悬垂指针: 当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址。

13.5.1定义智能指针类
1.引入引用计数:每次创建对象时,引用计数置1,每次拷贝构造时,增加引用计数。

14章 重载操作符与转换
14.1重载操作符的定义:operator后接徐定义的操作符符号。具有返回值和形参表
2.重载操作符必须具有一个类类型操作数:重载操作符必须具有至少一个类类型或枚举类型的操作数,这条规则强制重载操作符不能重新定义用于内置类型对象的操作符的含义。
优先级和结合性是固定的。
不再具备短路求值特性。

item1+=item2;
item1.operator+=(item2);
两个语句豆浆item2的值加至item1,第一种情况下,使用表达式语法隐式调用重载操作符函数,第二种情况下,在item1对象上调用成员操作符函数。

不要重载具有内置含义的操作符:重载逗号,取地址,逻辑与,逻辑或等操作符通常不是好做法,这些操作符具有有用的内置含义,如果我们定义了自己的版本,就不能在使用这些内置含义。
5.选择成员或非成员实现
1.赋值=,下表[] 调用() 和成员访问箭头-> 等操作符必须定义为成员,将这些擦偶偶符定义为非成员函数见在编译时标记为错误。
2.像复制一样,复合赋值操作符通常应定义为类的成员,与复制不同的是,不一定非得这样做,如果定义非成员复合赋值操作符,不会出现编译错误。
3.改变对象状态或与给定类型紧密联系的其他一些操作符,如自增,自减和解引用,通常应定义为类成员。
4.对称的操作符,如算术操作符,相等操作符,关系操作符和位操作符,最好定义为普通的非成员函数。
14.2输入输出操作符
即定义了算术操作符有定义了相关复合赋值操作符的类,一般应使用复合赋值实现算术操作符。
赋值操作符可以重载,无论形参为何种类型,赋值操作符必须定义为成员函数,这一点与复合操作符有所不同。
函数调用操作符必须声明为成员函数。一个类可以定义函数调用操作符的多个版本,有形参的数目或类型加以区别。
小结:
第五章介绍了C++为内置类型所定义的丰富的操作符集合,盖章也涵盖了标准转换,标准转换自动将操作符从一个类型转换为另一个类型。
通过定义内置操作符的重载版本,我们可以为自己的类型的对象定义同样丰富的表达式集合,重载操作符必须具有至少一个类类型或枚举类型的操作数,应用于内置类型时,冲澡操作符与对应操作符具有同样数目的操作数,同样的结合性和优先级。
大多数重载草祖父可以定义为类成员或普通非成员函数,赋值操作符,下表操作符,调用操作符和箭头操作符必须为类成员,操作符定义为成员时,他是普通成员函数,具体而言,成员操作符有一个隐式this指针,该指针一定是第一个操作符,即,一元操作符唯一的操作数,二元操作符的左操作数。
重载了operator() (即函数调用操作符)的类的对象,称为函数对象,这种对象通常用于定义与标准算法结合使用的谓词函数。
类可以定义转换,当一个类型的对象用在需要另一个不同类型对象的地方时,自动应用这些转换,接受单个形参且未指定explicit的构造函数定义了从其他类型到类类型的转换,重载操作符转换函数则定义了从类类型到其他类型的转换。传唤操作符必须为所转换类的成员,没有形参并且不定义返回值,转换操作符返回操作符所具有类型的值,例如:operator int 返回int。
重载操作符和类类型缓缓有助于更容易,更自然的使用类型,但是,必须注意避免设计对用户而言不明显的操作符和转关,而且应避免定义一个类型和另一个类型之间的多个转换。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: