首页 > 代码库 > [读书笔记]《C++primer》第四章

[读书笔记]《C++primer》第四章

4.1 基础

 

4.1.1 基本概念

  • 组合运算符合和运算对象

    • 运算符的优先级

    • 结合律

    • 运算对象的求值对象

  • 运算对象转换

  • 重载运算符

  • 左值和右值

 

4.1.2 优先级与结合律

 

  括号无视优先级与结合律,被括起来的部分被当成一个单元来求值,然后再与其他部分一起按照优先级组合。

  一般的组合运算只需要注意运算符的优先级和运算符的结合律即可。

 

4.1.3 求值顺序

 

  在大多数情况下,求值顺序是不明确的,比如:

    int i = f1() * f2();

  我们知道f1和f2在乘法执行之前一定会被调用,但我们不知道是f1和f2的先后调用顺序,所以我们在写代码的时候应当注意代码逻辑是否正确。

  只有四种运算符明确规定了运算对象的求值顺序:逻辑与(&&)、逻辑或(||)、条件(?:)、和逗号(,)。

 

*4.2 算术运算符

 

  算术运算符:一元正号(+)、一元负号(-)、乘法(*)、除法(\)、求余(%)、加法(+)、减法(-)。

 

*4.3 逻辑和关系运算符

 

  逻辑运算符:逻辑非(!)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)、相等(==)、不相等(!=)、逻辑与(&&)、逻辑或(||)。

 

 

*4.4 赋值运算符

 

  赋值运算符:赋值(=)。

 

  赋值运算满足右结合律,这一点和其他二元运算符不太一样。

  赋值运算符优先级较低。

 

4.5 递增和递减运算符

 

  注意一点即可:递增运算符(或递减运算符)优先级高于解引用运算符,即:

  pbeg++等效于(pbeg++)

  不过,尽管pbeg先自增,但后置自增运算符返回的却是初始值的副本。所以我们看起来像是:

  *pbeg;

  pbeg++;

 

4.6 成员访问运算符

 

  点运算符(.)和箭头运算符(->)都可以用来访问成员。

 

4.7 条件运算符

 

  条件运算符(?:),使用形式:cond?expr1:expr2;

  允许在条件运算符嵌套另外一个条件运算符,我们容易看出cond代表一个布尔值,而expr则没有对值有任何限制,嵌套的方法便浮出水面。

 

4.8 位运算符

 

  移位运算符:左移(<<)、右移(>>),左移在右侧插入值为0的二进制位,右移的行为依赖于其左侧运算对象的类型,如果是无符号类型自然在左侧插入0,如  果是带符号类型则在左侧插入符号位副本或者0。

  位取反运算符:位取反(~),将运算对象逐一求反后生成一个新值。

  位与、位或、位异或运算符:与(&)、或(|)、异或(^),与表示如果两个运算对象的对应位置都为1则运算结果该位为1,否则为0,或表示如果两个运算对象  的对应位置有一个为1则运算结果该位为1,否则为0,异或表示如果两个运算对象的对应位置只有一个为1则运算结果该位为1,否则为0。

  IO运算符(又叫移位运算符):左移(<<)、右移(>>),满足左结合律。

 

4.9 sizeof运算符

 

  sizeof运算符返回一条表达式或一个类型名字所占的字节数,使用:

    • sizeof(type)

    • sizeof expr

  在sizeof的运算对象中解析引用一个无效指针仍然是一种安全的行为,因为指针实际上并没有被真正使用。

  sizeof运算符的结果部分依赖于其作用的类型:

  • 对char或者类型为char的表达式执行sizeof运算,结果为1。

  • 对引用类型执行sizeof运算得到被引用对象所占空间的大小。

  • 对指针执行sizeof运算得到指针本身所占空间的大小。

  • 对解引用指针执行sizeof运算得到指针指向的对象所占空间的大小,指针不需要有效。

  • 对数组执行sizeof运算得到整个数组所占空间的大小,等价于对数组中所有的元素各执行一次sizeof运算并将所得结果求和。注意,sizeof运算不会把数组转换成指针来处理。

  • 对string对象或vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。

    • 因为执行sizeof运算可以得到整个数组的大小,所以可以用数组的大小除以单个元素的大小得到数组中的元素的个数。

 

4.10 逗号运算符

 

  逗号运算符含有两个运算对象,按照从左到右的顺序依次求值。和逻辑与、逻辑或以及条件运算符一样,逗号运算符也规定了运算对象求值的顺序。

 

4.11 类型转换

 

  在c++语言中,某些类型之间有关联,当程序需要其中一种类型的对象时,可以用另一种关联类型的对象或值来替代。

  何时发生隐式转换:

  • 在大多数情况下,比int类型小的整型值首先提升为较大的整数类型。

  • 在条件中,非布尔值转换成布尔类型。

  • 初始化过程中,初始值转换成变量的类型值;在赋值语句中,右侧运算对象转换成左侧运算对象的类型。

  • 如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。

  • 函数调用时也会发生类型转换。

 

4.11.1 算术转换

 

  整型提升负责把小整数类型转换成较大的整数类型。对于bool、char、signed char、unsigned char、short和unsigned short等类型来说,只要它们所有可能的值都  存在int里,它们就会提升成int类型;否则,提升成unsignedint类型。

  无符号类型的运算对象如果和带符号类型的运算对象一起,要看谁“包”的住谁。

 

4.11.2 其他隐式类型转换

 

  数组转换成指针:大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针。

  指针的转换:常量整数值0或者字面值nullptr能转换成任意指针类型;指向任意非常量的指针能换成void*;指向任意对象的指针能转换成const void*。

 

[读书笔记]《C++primer》第四章