4.1 基础

  • 函数调用也是一种特殊的运算符,它对运算对象的数量没有限制。
  • C++ 的表达式要么是左值,要么是右值。左值可以位于赋值语句的左边,右值则不可以。
  • 当一个对象被用作右值的时候,用的是对象的值;当对象被用作左值的时候,用的是对象的身份。

    【mark】
  • 优先级规定了运算对象的组合方式,但是没有说明运算对象的求值顺序,一般不会明确指定求值顺序。
  • 对于没有指定执行顺序的运算符,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。
cout << i << ++i << endl; // 未定义的

4.2 算术运算符

  • 算术运算符的运算对象和求值结果都是右值。
  • 在表达式求值之前,小整数类型的运算对象被提升成较大的整数类型,所有运算对象最终会转换成同一类型。
  • 一元正(负)号运算符作用于一个指针或者算数值时,返回运算对象(取负)的提升后的副本。
bool b = true;
bool b2 = -b; // b2 is true
  • m = (m / n) * n + m % n,则 m % n 符号与 m 相同。

4.3 逻辑和关系运算符

  • 逻辑和关系运算符的运算对象以及求值结果都是右值。
  • 相等性测试与布尔字面值
if (val) {} // 如果 val 是任意的非 0 值
if (!val) {} // 如果 val 是 0
if (val == true) // 如果 val 等于 1

4.4 赋值运算符

  • 赋值运算符的左侧对象必须是一个可修改的左值。
int i = 0, j = 0, k = 0; // 初始化而非赋值
const int ci = i; // 初始化而非赋值
1024 = k; // 错误 字面值是右值
i + j = k; // 错误 算术表达式是右值
ci = k; // 错误 ci 是常量左值
  • 赋值运算的结果是它的左侧对象,并且是一个左值,结果的类型是左侧运算对象的类型。
  • 赋值运算符满足右结合律。

4.5 递增和递减运算符

  • 递增和递减运算符有两种形式:前置版本 ++i 和后置版本 i++。这两种运算符必须作用于左值运算对象,前置版本将对象本身作为左值返回,后置版本将对象原始值的副本作为右值返回。
  • 除非必须,否则不用递增和递减运算符的后置版本。

4.6 成员访问运算符

  • ptr->mem == (*ptr).mem

4.7 条件运算符

4.8 位运算符

  • 位运算符的运算对象如果是“小整型”,则会被自动提升为整数类型。
  • 位运算符如何处理带符号数的符号位是未定义的,因此建议仅将位运算符用于处理无符号数。
  • 移位运算符(IO运算符)满足左结合律。

sizeof 运算符

  • sizeof 运算符返回一条表达式或者一个类型名字所占的字节数,返回 size_t 类型的常量表达式。
sizeof (type)
sizeof expr
  • sizeof 运算符满足右结合律。
  • sizeof 的运算对象中解引用一个无效指针是安全的,因为指针没有被真正使用。
  • 对数组执行 sizeof 运算得到整个数组的大小,对 sting 或 vector 执行 sizeof 运算只返回该类型固定部分的大小。

4.10 逗号运算符

  • 逗号运算符先对左侧的表达式求值,然后将结果丢弃掉,再对右侧的表达式求值,返回右侧的结果。

4.11 类型转换

  • 算术转换:运算符的运算对象将转换成最宽的类型。
  • 整型提升:转换后的类型要容纳原类型所有可能的值。
  • 如果一个运算对象是无符号类型,另一个是带符号类型:

    无符号类型不小于带符号类型:带符号类型转成无符号类型;

    带符号类型大于无符号类型:转换结果依赖于机器;
  • 指针的转换

    常量整数值 0 或者字面值 nullptr 能转换成任意指针类型;

    指向任意非常量的指针能转成 void

    指向任意对象的指针能转成 const void
  • 转换成布尔类型:指针或算术值为 0,结果为 false,否则为 true。
  • 转换成常量:允许将指向非常量的指针(引用)转换成相应的常量指针(引用)。
  • 类类型能定义由编译器自动执行的转换,不过编译器每次只能执行一次类类型的转换。
  • 强制转换
cast-name <type> (expression)
  • static_cast
// 把一个较大的算术类型赋值给较小的类型。
double slope = static_cast<double>(j) / i;
// 找回存在于 void* 指针的值
double *p = static_cast<double*>(p);
  • const_cast
// 改变运算对象的底层 const
const char *pc;
char *p = const_cast<char*>(pc);
  • reinterpret_cast
// todo

C++ Primer 5 CH4 表达式的更多相关文章

  1. C++ Primer 笔记——lambda表达式

    1.一个lambda表达式表示一个可调用的代码单元,可以理解为一个未命名的内联函数,但是与函数不同,lambda表达式可能定义在函数内部.其形式如下: [capture list] (paramete ...

  2. C++ Primer笔记

    C++ Primer笔记 ch2 变量和基本类型 声明 extern int i; extern int i = 3.14;//定义 左值引用(绑定零一变量初始值,别名) 不能定义引用的引用:引用必须 ...

  3. C Primer Plus_第5章_运算符、表达式和语句_编程练习

    Practice 1. 输入分钟输出对应的小时和分钟. #include #define MIN_PER_H 60 int main(void) { int mins, hours, minutes; ...

  4. C++_系列自学课程_第_10_课_表达式_《C++ Primer 第四版》

    程序设计语言中大部分程序都在进行表达式的求值操作, 例如求两个数的和,求一个表达式的逻辑结果,或者通过输入输出表达式语句进行输入和输出. 这里我们对表达式进行讨论. 一.表达式 1.表达式 表达式由一 ...

  5. 《C++primer》v5 第4章 表达式 读书笔记 习题答案

    4.1 105 4.2 *vec.begin()=*(vec.begin())//先调用点运算符,再解引用 *vec.begin()+1=(*vec.begin())+1//先解引用,再加一 4.3略 ...

  6. 【C语言学习】《C Primer Plus》第5章 运算符、表达式和语句

    学习总结 1.有了一定的语言基础,运算符和表达式这些都大同小异,无外乎赋值运算符(=).算术运算符(+.-.*./.%.++.——)和其他的一下运算符(sizeof.(type)). 2.声明一个参数 ...

  7. 学习C++.Primer.Plus 5 循环和关系表达式

    C++将赋值表达式的值定义为左侧成员的值 赋值操作符是自右向左结合的 cout.setf(ios:: boolalpha);//调用设置标记,命令cout输出true或false,而非1或0. 任何表 ...

  8. C++ Primer : 第十章 : 泛型算法 之 lambda表达式和bind函数

    一.lambda表达式 lambda表达式原型: [capture list] (parameter list) -> retrue type { function body } 一个lambd ...

  9. 【足迹C++primer】表达式求值

    表达式求值 /** * 功能:表达式求值(0到9) * 时间:2014年6月15日08:02:31 * 作者:cutter_point */ #include<stdlib.h> #inc ...

随机推荐

  1. [个人翻译]GitHub指导文件(GitHub Guides[Hello World])

    [个人翻译]GitHub指导文件(GitHub Guides[Hello World]) Mirage_j个人翻译,欢迎转载,最好标明出处http://www.cnblogs.com/mirageJ/ ...

  2. Git 和 GitHub 使用

    Git和GitHub的使用 Git是一款免费.开源的分布式版本控制系统. GitHub托管远程仓库,并提供一个web界面. 有2种协议支持从本地push代码到远程仓库. 一种是http,需要输入用户名 ...

  3. UITableView、UICollectionView行高/尺寸自适应

    UITableView 我们都知道UITableView从iOS 8开始实现行高的自适应相对比较简单,首先必须设置estimatedRowHeight给出预估高度,设置rowHeight为UITabl ...

  4. gRPC中Any类型的使用(Java和NodeJs端)

    工作中要把原来Java服务端基于SpringMVC的服务改为使用gRPC直接调用.由于原Service的返回值为动态的Map类型,key值不确定,且value的类型不唯一,因此使用了protobuf ...

  5. Ninject之旅之十二:Ninject在Windows Form程序上的应用(附程序下载)

    摘要: 下面的几篇文章介绍如何使用Ninject创建不同类型的应用系统.包括: Windows Form应用系统 ASP.NET MVC应用系统 ASP.NET Web Form应用系统 尽管对于不同 ...

  6. Vuex 模块化与项目实例 (2.0)

    Vuex 强调使用单一状态树,即在一个项目里只有一个 store,这个 store 集中管理了项目中所有的数据以及对数据的操作行为.但是这样带来的问题是 store 可能会非常臃肿庞大不易维护,所以就 ...

  7. 一篇知乎的故事 - javascript技术贴

    前言 就像文章题目所示,本文的发表源于知乎的一篇文章.文章链接如下:如果你想靠前端技术还房贷,你不能连这个都不会.这篇文章是群里水群时别人发的,像我这样的菜鸟角色才不会逛知乎~~~.这篇文章主要是讲了 ...

  8. 如何修改Window系统下PATH路径以及win8下masm32V11

    如何修改Window系统下PATH路径   //其实这个都是临时性的, 退出dos窗口就没有用了,只是做个笔记罢了   C:\Users\Administrator>    set path=E ...

  9. Spring源码解析三:IOC容器的依赖注入

    一般情况下,依赖注入的过程是发生在用户第一次向容器索要Bean是触发的,而触发依赖注入的地方就是BeanFactory的getBean方法. 这里以DefaultListableBeanFactory ...

  10. struts2中Action到底是什么,怎么理解

    struts2中Action到底是什么,怎么理解 1.配置完web.xml2.创建视图页面login.jsp3.创建业务控制器LoginAction类(解释说:创建业务控制器LoginAction类, ...