C++Primer第5章[知识教育]_第1页
C++Primer第5章[知识教育]_第2页
C++Primer第5章[知识教育]_第3页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1. C提供了丰富的操作符,并定义了对于内置操作数的这些操作符的含义。并且,C支持操作符重载。允许程序员自定义用于类类型的操作符含义。标准库正是使用重载来定义用于库类型的操作符的。本章重点介绍C定义的操作符。它无使用内置类型的操作数。另外,还介绍一些标准库定义的操作。本章其实是C中基本的操作。我无的学习,不仅要学习与C语言的区别,更主要的是理解一些库操作符。以及C在面向对象方面所作的改进。2.一个表达式由多个操作数通过操作符组合而成。操作数我无以前学过。操作符是可有可无的。每个表达式都会产生一个结果。若表达式中无操作符,则结果是操作数本身。若有表达式,其值通过对操作数作指定操作而获得。表达式的

2、结果是右值。可读取,但不能赋值。操作符表示该 操作符执行什么操作及操作结果的类型,这取决于操作数的类型。除非已知操作数的类型,否则无法确下表达式的含义。例:i+j=?可能是两个字符串相加,也可能是两个数相加。取决于操作数的类型。 一元,二元,三元操作符:有几个操作数义称为几元操作符。 操作符对其操作数的类型有要求。如果操作符应用于内置或复合类型,由C定义其类型要求。这也是我无主要要学习的内容。对于类类型,要由类的定义者通过操作行重载的方式定义操作符的操作。对于内置类型操作数的二元操作符,通党要求它的两个操作数具有相同的数据类型。或者其类型可以转同一种数据类型。3. 算术操作符可用于任意算术类型

3、或可转换为算术类型的数据类型。其优先级由上往下排。高优先级的顺序操作符要比低优先级的结合更紧密。都是左结合,即,当优先级相同时,从左向右依次与操作数结合。一元负号及一元正号对于操作数取正或取负值操作。4. 设某位机器的short为16位。能表示的最大值为32767.上例中,相加后的结果是32768.这个有符号数需要17位存储空间。但这里只有16位数。于是导致了溢出现象的发生。许多系统都不会给出编译时或运行时警告。对于不同机器,上式的值不尽相同。有可能是堆断后得到327686.关系和逻辑操作符使用算术或指针类型操作数并返回bool类型的值。按优先级顺序排列如下。7.逻辑与和逻辑或操作符总是先计算

4、其左操作数,然后再计算其右操作数。只有当左操作数的值无法确定逻辑表达式的结果时,才会求解右操作数。我们将这种求值策略称为短路求值。 对于逻辑与操作符,一个很有价值的用法是,如果某边界条件使exp2的计算变得危险,则应在该 条件出现之前,先让exp1的计算结果为false. 上述程序是将句子的第一个单词变在大写。在while中判断两个条件,首先,检查it是否如果已到达结尾。如果不是,则it肯定指向s中的一个字符。只有当该条件成立时,系统才会计算逻辑与操作的右操作数。即保证it确实指向一个真正的字符后,才检查它是否为空格。 9. 只要k大于1,上式结果为true.11. 位操作符应用整型数做操作数

5、。将其视为二进制位的集合,为每一位提供检验和设置的功能。还可用于bitset类型的的操作数。语法规定位操作符的整数类型可以是有符号的也可以是无符号的。但如果操作数为负数,则位操作符如何处理其符号位依赖于机器。它们的应用可能不同,在一个应用环境中实现的程序可能无法应用于另一个应用环境。对于12.左移或右移时会丢弃移出去的位。给左右两边插入0.对于右移操作,如果其操作数是无符号的,则从左边开始插入0.如果操作数是有符号的,则插入符号位的副本或0.如何选择依据具体实现。移位操作的右操作数不可以是负数,而且必须是严格小于左操作数位数的值。否则操作结果未定义。常犯的错误是位与与逻辑与,位或与逻辑或相混淆

6、。14. Bitset类比整型值上的低级位操作更容易使用。设某班30个学生,测验,及格用1不及格为0.对每个学生用一个二进制位来记录一次测验的结果。可用bist类型或整型值来代表一次测验结果。上述定义中,bitset每一位都默认为0.整形一定要用unsigned long。因为它可保证在任何机器上都至少有32位长度。设第27号学生及格了。操作分别如下:用bitset实现时,可直接传递要置位的位给set函数。用unsigned long实现时,就比较复杂。|=是一个复合赋值操作符。 若老师重新复查成绩,发现第27号学生实际上是不及格的。则用以下方式修改。 也可用以下方式获知第27号同学是否及格。

7、 一般而言,标准库提供的bitset操作更直接、更容易阅读和书写。正确使用的可能性更高。而且,bitset对象的大小不受unsigned数的位数限制。通常来说,bitset优于敕型数据的低级直接位操作。15.标准IO库重载了位操作符和用于输入和输出。重载的操作符与该操作符的内置类型版本具有相同的优先级和结合性。最后一句的含义是:将10写到cout,然后用此操作的结果即cout与42做比较。16.赋值表达式的值是其左操作数的值,其结果的类型为左操作数的类型。赋值时,当左、右操作数的类型不同时,有可能通过隐式类型转换修改被赋的值。因此,存放在左、右操作数中的值并不相同。J最后一个赋值语句中,iva

8、l的值与右操作数的值不相同。17.在多个赋值操作中,各对象必须具有相同的数据类型,或具有可转换为同一类型的数据类。18.另一种常见的作法是将赋值操作写在条件表达式中。这样可缩短程序代码并阐明程序员的意较长。上例中循环调用get_value函数,设它返回int值,通过循环检查这些返回值,直到荼得所需值为止。它可简化为:但是下面的程序更能清晰地表达程序员的意较长:持续循环直到get_value的值 为42为止。要注意的是,在赋值操作上加圆括号是必须的。因为赋值操作符的优先级低于不等操作符。若没有圆括号,则先比较get_value的返回值和42是否相等,然后将比较的结果true或false即1或0赋

9、给i.这显然不是我们想要的。 另一种容易出现的错误是混淆相等操作符和赋值操作符。前面一个对于if语句的判断总为true. 这类错误往往难以发现,但会导致程序执行时得不到想要的结果。19. 我们常在对某个对象做某种操作后,再将操作的结果重新赋给该对象。为此,C+提供了复合赋值操作符。虽然运算结果等价。但还是有差另的。在使用复合赋值操作时,左操作数只计算了一次,而使用相似的长表达式时,该操作数计算了两次。第一次作为右操作数,第二次作为左操作数。复合赋值的性能比一般好。若不考虑性能因素,在很多上下文环境中这两个是相似的。20.+和- -被称为自增和自减操作符。它为对象加1或减1操作提供了方便简短的实

10、现方式。建议使用前自增。因为前置操作需要做的工作更少,它只需要加1后返回加1后的结果。后自增操作则必须先何存操作数原来的值,以便在结束后返回未加1之前的值作为操作结果。对于int型对象和指针,编译器可优化掉这项额外工作。但对于更多的复杂迭代器类型,这种额外工作可能会花费更大的代价。因此,养成使用前置操作这个好习惯,就不必操心性能差异的问题。22. 点操作符用于获取类类型对象的成员。若有一个指向Sales_itme对象的指针,在使用点操作符前,需要对该指针进行解引用。这里,对sp进行解引用以获得指定的Sales_item对象。然后使用点操作符调用指定对象的成员函数。注意必须用圆括号把解引用括起来

11、。因为点操作符的优先级高于解引用。若漏掉圆括号,则含义完全不同。由于sp是没有成员的指针。所以会出错。 由于编程时很容易忘记圆括号,而这类代码又经常使用,所以C+为在点操作符后使用解引用操作定义了一个同义词:箭头操作符。 设p为指向类类型对象的指针。Same_isbn可重写为:23. 是唯一的三元操作符。它允许将简单的if-else判断语句嵌入到表达式中。首先计算条件判断表达式cond的值。如果cond为0,则计算expr2,为非0,则计算exper1. 与逻辑与,逻辑或操作符一样,条件操作符保证了上述操作数的求解次序。 由于条件操作符的优先级相当低。当我们要在一个更大的表达式中嵌入条件表达式

12、时,通常必须用圆括号把条件表达式括起来。否则会有意外的结果24. 第二个将i和j的结果视为操作符的操作数。输出1或0.输出cout值,然后将返回结果cout作为条件操作符的判断条件。25. Sizeof表达式的结果是编译时常量。有以下三种语法形式:将sizeof用在表达式expr上,将获得该表达式的结果的类型长度。将sizeof用于表达式时,并没有计算表达式的值。在sizeof *P中,指针p可以持一个无效地址。因为不需要对p做解引用扣作。26. 因为sizeof返回整个数组在内存中的存储长度,所以用sizeof数组的结果除以sizeof其元素类型的结果,即可求出数组元素的个数。设ia为一数组

13、,28. 含有两个或更多操作符的表达式称为复合表达式。其中操作数和操作符的结合方式决定了整个靛达式的值。这取决于操作符的优先级和结合性。若不想考虑优先级和结合性,则可用圆括号强制实现某个特殊分组。P14729. 以什么次序求解操作数通常没有多大关系。只有当操作符的两个操作数涉及到同一个对象,并改变其值时,计算次序才会影响结果。如果一个子表达式修改了另一个子表达式的操作数,则操作数的求解次序就变得相当重要了。操作符的左右操作数都使用了index变量。但是左操作数更改了该变量。这类表达式的行为没有明确定义。30. 一个表达式里,不要在两个或更多的子表达式中对同一对象做自增或自减操作。31. New

14、和delete不仅可以动态创建和释放数组,也可用于动态创建和释放单个对象。定义变量时,必须指定其数据类型和名字。动态创建对象时,只需指定其数据类型,不必为该对象命名。New返回指向新创建对象的指针。我们通过该指针来访问此对象。 该对象在自由存储区中分配创建了一个整型对象,并返回此对象的地址。并用该地址初始化指针pi. 提供了初值后,new表达式分配到所需要的内存后,用给定的初值初始化该内存空间。32.如果不提供显式初始化,动态创建对象与在函数内定义的变量初始化方式相同。程序员可以通过在类型名后面使用一对内容为空的圆括号对动态创建的对象做值初始化。内容为空的圆括号表示虽然要做初始化,但实际上并未

15、提供特定的初值。对于提供了默认构造函数的类类型,没有必要对其对象进行值初始化。无论程序是明确地不初始化还是进行值初始化,都会调用其默认构造函数初化。对于内置类型或没有定义默认构造函数的类类型,采用不同初始化方式是有显著的差别的。33.值初始化的()必须置于类型名后面,而不是变量后面。34.delete释放指针所指向的地址空间。如果指针指向的不是new分配的内存地址,则在该指针上使用delete是不合法的。上述几个例子中,编译器可能会拒绝str的delete.编译器知道str并不是一个指针,因此会在编译时就能检查出这个错误。第二个错误则比较隐蔽:通常来说,编译器不能断定一个指针指向什么类型的对象

16、,因此尽管这个语句是错误的,但在大部分编译器上仍能通过。35.执行delete ip后,ip没有定义。但在很多机器上,尽管ip没有定义,但仍然存放了它之前所指向对象的地址。但它所指向的内存已被释放,ip不再有效。这样的指针变成悬垂指针。县垂指针指向曾经存放对象的内存,但该对象已经不再存在了。往往会导致程序的错误,而且很难检测出来。一旦删除了指针所指向的对象,应立即将指针置为0.这样就非常清楚地表明指针不再指向任何对象。36. 动态创建的const对象必须在创建时初始化。并且一经初始化,其值就不能再修改。New表达式返回指向int型的const对象的指针。与其他const对象的地址一样,由于ne

17、w返回的地址上放的是const对象,该地址只能赋给指向const的指针。 对于类类型的const动态对象,如果该类提供了默认构造函数,则可陷式初始化。内置类型对象或未提供默认构造函数类类型对象必须显式初始化。 尽管程序员不能改变const对象的值,但可以撤销对象。可以用delete删除。 动态37. 无法将该块内存返还给自由存储区。删除动态分配内存失败称为内存泄露。内存泄露很难发现。一般需等程序运行一段时间后,耗尽了所有内存空间时,内存泄露才会显露出来。 如果删除指针所指向的对象后,将指针置为0,则比较容易检测出这类错误。 当两个指针指向同一个动态创建的对象,删除时就会发生错误。如果在其中一个

18、指针上做delete运算,将该对象的内存空间返还给自由存储区,然后接着delete第二个指针,则自由存储区可能会被破坏。38.如果两个类型之间可以相互转换,则称这两个类型相关。 隐式类型转换:由编译器自动执行,无需程序员介入。为孩止精度损失,如果表达式的操作数分别为整形和浮点型,则整型操作数被转换为浮点型。但左操作数类型不能改变。赋值时又将浮点型转换为整型。由于这种转换会导致精度损失,大多数编译器会给出警告。39.条件操作符中的第一个操作数及逻辑与&或|非!的操作数都是条件表达式,出现在if,while, for, do while句的同样是条件表达式。40. C+为内置类型提供了一组转换规则

19、,其中最常用的是算术转换。算术转换规则定义了一个类型转换层次,该层次规定了操作数应按什么交序转换为表达式中最宽的类型。在包含多种类型的表达式中,转换规则要确保计算值的精度。 最简单的转换为整型提升。对于所有比int小的整型,包括char, signed char, unsigned char, short和unsigned short,如果该类型的所有可能值都以包容在int 内,它们就会被提升为int 型。否则,它们将被提升为unsigned int. 如果将bool值提升为int,则false变为0, true为1. 包含short和int类型的表达式,short类型的值转换为int.如果i

20、nt型足够表示所有unsigned short,则将unsigned short转换为int,否则,将两个操作数均转换为unsigned int. long和unsigned int的转换也是一样。只要机器上的long足够表示unsigned int的所有值,则将unsigned int转换为long,否则,将两个操作数均转换为unsigned long. 在32位机上,long和int常用一个字长表示,当表达式包含unsigned int和long时,其操作数都应转换为unsigned long型。 对于包含signed和unsigned int型的表达式,其转换结果可能会出乎意料。表达式中

21、的signed 型会被转换为unsigned型。41. 下例中,要私是将操作数转换为表达式中的最大类型,要么是在赋值表达式中将右操作数转换为左操作数的类型。42. 不将数组转换为指针的例外情况有:数组用作取地址(&)操作符的操作数或sizeof操作符的操作数时,或用数组对数组的引用进行初始化时,不会将数组转换为指针。另外,在C+中,还提供了另外两种指针转换。指向任意数据类型的指针都可转换为void*类型,整型数值常量0可转换为任意指针类型。43. 可将算术对象转换为bool类型,bool对象也可转换为int 型。将算术类型转为bool时,零为false其他为true. 将bool 对象转换为算

22、术类型时,true为1,false为0.44. 将枚举对象或枚举成员提升为什么类型由机器定义。并且依赖于枚举成员的最大值。无论其最大值是什么,enum对象或枚举成员至少提升为int型。如果int型无法表示枚举成员的最大值,则提升到能表示所有枚举成员值的、大于int 型的最小类型。(unsigned int, long或unsigned long)46. 类类型可以定义由编译器自动执行的类型转换。比如,从istream中读取数据,并将此表达式作为while循环的条件。这里隐式使用了IO标准库定义的类型转换。While循环条件应为bool类型的值,但此时给出的却是istream类类型的值。于是,istream类型的值应转换为bool类型。将istream类型转换为bool类型意味着要检验流的状态。如果最后一次读cin的尝试是成功的,则流的状态将导至上述类型转换为boo类型后获得true值。While循环条件成立。如果最后一次尝试失败,比如已读到文件尾或无效输入,此时将istream类型转换为bool类型后得false,while循环

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论