第四章 摘录

4.1基础
作用于一个运算对象的运算符是一元运算符,两个则是二元运算符,还有一个作用于三个运算对象的三元运算符。函数调用也是一种特殊的运算符,运算对象数量没有限制。

c++的表达式要不然是右值,要不然就是左值。在c++语言中,二者的区别就没那么简单了。当一个对象被用作右值的时候,用的是对象的值(内容);当被用作左值的时候,用的是对象的身份(在内存中的位置)。
关于左右值可以参考:https://www.zhihu.com/question/23520802

对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会引发错误并产生未定义的行为。如int i = 0;
cout << i <<" " << ++i <<endl; //未定义的

bool b = true; bool b2 = -b; //b2是true 因为c++中布尔值不应该参与运算。如果直接cout << -b <<endl;会输出-1。上述情况下输出b2还会是1,原因是int型的-1又被转换为bool值,不为0即为true。

4.2算术运算符
参与取余运算的运算对象必须是整数类型。

4.3 逻辑和关系运算符
if (i < j < k) //若k大于1则为真。先判断i<j,返回的bool值作为第二个运算符的左侧运算对象。

if (val)很合理,但是if (val == true)就不太合理,因为true这个bool值会先转换为val的类型,如转换为1,就变为了if(val == 1)了。如果真想知道val的值是不是1,直接写出1这个数值就好了,而不要与true 比较。

4.4赋值运算符
int i = 0, j = 0 , k = 0; const int ci = i;
1024 = k; //错误:字面值是右值
i + j = k; //错误:算术表达式是右值
ci = k ; //错误:ci是常量左值

赋值运算符满足右结合律。 int ival, jval; ival = jval = 0;

复合赋值运算中,唯一的区别是左侧运算对象的求值次数,使用复合运算符只求值一次,使用普通运算符求值两次。这两次包括:一次作为右边子表达式的一部分求值,另一次是作为赋值运算的左侧运算对象求值。

4.5递增和递减运算符
递增和递减运算符有 前置版本 和 后置版本。前置版本首先将运算对象加1(或减1),然后将改变后的对象作为求值结果。而后置版本也会将运算对象加1(或减1),但是求值结果是运算对象改变之前那个值的副本。
int i = 0, j;
j = ++i; // j = 1, i = 1
j = i++; // j = 1, i = 2

建议:除非必须,否则不用后置版本。
因为前置版本避免了不必要的工作,把值加1后直接返回改变了的运算对象。而后置版本需要将原始值存储下来以便于返回这个未修改的内容。如果我们不需要修改前的值,这个操作就是一种浪费。

如果想既将变量加1减1又能使用原来的值,就用后置版本。
如:auto pbeg = v.begin();
while (pbeg != v.end() && pbeg >= 0 )
cout << pbeg++ << endl;
对于的
pbeg++,后置递增运算符的优先级是大于解引用运算符的。其实质是,先将pbeg指针加1,然后返回pbeg的初始值的副本作为其求值结果,再解引用。所以,会输出当前值并将pbeg向前移动一个元素。即,后置递增运算符返回初始的未加1的值。
另:
pbeg++,这是一种被广泛使用并且有效的写法。

while (beg != s.end() && !isspace(*beg))
beg = toupper(beg++) //错误:该赋值语句未定义
上述情况问题在于:赋值运算符左右两端都用到了beg,并且右侧的运算对象还改变了beg的值,所以它是未定义的。有可能它会这么处理该表达式:

  1. beg = toupper(beg); //先求左侧值
  2. (beg+1) = toupper(beg); //先求右侧值

4.6 成员访问运算符
点运算符和箭头运算符;ptr->mem等价于(ptr).mem
解引用符的优先级低于点运算符。
箭头运算符作用于一个指针类型的运算对象,结果是一个左值。点运算符分成两种情况:如果成员所属的对象是左值,那么结果是左值;反之,如果成员所属的对象是右值,那么结果是右值。
iter++->empty(); 等价于(
iter++).empty()。

4.7 条件运算符
4.8 位运算符
位运算符是作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。
~位求反运算符。^位异或运算符。

4.9 sizeof运算符
返回一条表达式或一个类型名字所占的字节数。
sizeof *p:在sizeof的运算对象中解引用一个无效指针仍然是一种安全的行为,因为指针实际上并没有被真正使用。
sizeof无需我们提供一个具体的对象,因为要想知道类成员的大小无须真的获取该成员。

4.10 逗号运算符
4.11.1算术转换
算术转换的规则定义了一套类型转换的层次,其中运算符的运算对象转换成最宽的类型。
整型提升,负责把小整数类型(bool、char、unsigned char、unsigned short)转换成较大的整数类型。只要它们所有可能的值都能存在int里,就会提升成int类型,否则提升成unsigned int类型。
较大的char类型(wchar_t、char16_t、char32_t)提升成int、unsigned int、long、unsigned long、long long和unsigned long long中最小的类型,前提是转换后的类型要能容纳原类型所有的值。

4.11.2隐式类型转换
数组转换成指针:在大多数用到数组的表达式中,数组自动转换成指向数组首元素的指针,当数组被用作decltype关键字的参数或者作为取地址符、sizeof及typeid等运算符的运算对象时,上述转换不会发生。

4.11.3显式转换
强制类型转换(cast),尽管有时不得不使用这种强制类型转换,但这种方法本质上非常危险。
一个命名的强制类型转换具有如下形式:
cast-name<type>(expression);
其中type是转换的目标类型而expression是要转换的值。如果type是引用类型,则结果是左值。cast-name是static_cast,dynamic_cast,const_cast和reinterpret_cast中的一种。cast-name指定了执行的是哪种转换。

static_cast:需要把一个较大算术类型赋值给较小类型时非常有用。此时强制类型转换告诉程序读者和编译器:我们知道并且不在乎潜在的精度损失。如double slope = static_cast<double>(j) / i;

const_cast:只能改变运算对象的底层const。
对于将常量对象转换为非常量对象的行为,我们一般称其为“去掉const性质”(cast away the const)。
如const char *pc; char p = const_cast<char>(pc);
const_cast常用于有函数重载的上下文中。

reinterpret_cast:通常为运算对象的位模式提供较低层次上的重新解释。
如:int *ip; char pc = reinterpret_cast<char>(ip);
我们必须牢记pc所指的真实对象是一个int而非字符,如果把pc当成普通的字符指针使用就可能在运行时发生错误。如: string str(pc); 可能导致异常的运行时行为。 使用reinterpret_cast是非常危险的!

建议:避免强制类型转换。且对于reinterpret_cast尤其适用。在有函数重载的上下文中使用const_cast无可厚非,但在其他情况下使用也就意味着程序存在某种设计缺陷。

早期版本的c++语言中,显式强制转换包含两种形式:
type (expr); //函数形式的强制转换
(type) expr; //c语言风格的强制转换

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,500评论 1 51
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,724评论 0 38
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,114评论 0 13
  • 比如我们在介绍经典影片《肖申克的救赎》时用开场四步法来准备开场: 第一步 定主角:因被诬告为杀人罪,而被关入肖申克...
    廖天鹏阅读 191评论 0 0
  • 为即将到来的面试紧张。 紧张到吃不下饭,胃痉挛,频繁得想要上厕所,脑子里全是明天面试的场景。单纯说来这...
    From旮旯阅读 495评论 0 0