c++primer 第四章 表达式

4.1 基础

4.1 基本概念

  • 重载运算符
    重载运算符,可重载运算的类型和返回的类型。运算对象的个数、运算符优先级、结合律都无法改变
  • 左值和右值
    • 简单理解,左值可以被赋值,右值不能被赋值。
    • 一个对象被用作左值,表示用的是对象的身份(在内存中的位置);被当作右值使用的时候,用的对象的值(内容)。
    • 需要右值的地方可以用左值代替,需要左值的地方不能用右值代替。
    • 作用于左值的符号:赋值运算符、取地址运算符、解引用运算符、下标运算符
    • decltype作用于表达式得到引用类
int *p;
decltype(*p) //int&,对p解引用 -》引用
decltype(&p) //int**,对p取地址得到的是p的地址-》int指针的地址

4.1.2 优先级结合律

理解左右结合律。
定义符号¥为二元运算符,计算1¥2¥3,若符合左结合律,求值顺序为(1¥2)¥3;若符合右结合律,求值顺序为1¥(2¥3)

4.1.3 求值顺序

  • <<没有明确规定何时、如何对运算对象求值。
int i=0;
//未定义,可能输出0,1或者1,1
cout<<i<<" "<<++i<<endl;
  • 有四种运算符规定了运算顺序:"&& “,”||", “?:”,"",从左到右计算。
  • f()+g()*h()+j()
    • 优先级要求g和h先相乘
    • 结合律要求f+乘积,再加j
    • 对函数的调用顺序没有要求,若函数内部影响同一对象,很可能出错。

4.2 算数运算符

在这里插入图片描述

  • 算数运算符的运算对象和结果都是右值
  • 所有运算对象都会转为同一类型,再进行运算
  • %:取余操作,
    • 参与取余操作的数必须是整数
    • m%n计算方法:将m、n的绝对值进行取余运算得数值部分,结果的正负性和m相同。

4.3 逻辑和关系运算符

在这里插入图片描述

  • &&||都是短路求值。从左往右计算时,对 &&,一个表达式为假,停止计算,表达式为假;对 ||,一个表达式为真,停止计算,表达式为真。
  • 在循环或传值时,比较大的对象应该声明成引用类型避免拷贝。不需要写操作时,应该声明成常量引用
  • i<j<k的写法,若k大于1,则一定为真。‘’val==true仅当val值为1,返回值才是true;

4.4 赋值运算符

  • c++允许花括号括起来的初始值列表作为赋值语句的右侧赋值对象。
  • 赋值满足右结合律。
  • 赋值运算符优先级较低。运算符可查看本页最后的表。

4.5 递增和递减运算符

  • 除非必要,否则不用递增递减的后置版本
  • 掌握对迭代器的常用方法*pbeg++:返回当前值,并向后移动。
  • 运算符可以按任意顺序求值。
//赋值和递增递减符同时使用行为未定义
*beg = toupper(*beg++)
*beg = toupper(*beg)//若先求左侧值
*(beg+1) = toupper(*beg)//若先求右侧值

4.6 成员访问运算符

  • ptr->mem等同于(*ptr).mem。由于.运算符登记高,所以必须加括号。

4.7 条件运算符

  • 条件运算符满足右结合律
  • 在输出表达式中使用条件运算符,因为条件运算符优先级很低,要将条件运算符括起来,输出才正确。
cout<<(grade<60?"fail":"pass")<<endl;//正确
cout<<grade<60?"fail":"pass"<<endl;//错误,输出grade后,尝试比较cout和60

4.8 位运算符

在这里插入图片描述

  • 位运算符作用于整数类型和bitset
  • 运算对象是小整型,值会被自动提升为int
  • 负数进行左移操作时,位运算符如何处理符号位依赖于机器;强烈建议位运算符只作用于无符号类型
  • IO运算符是移位运算符的重载,优先级比算术运算符低,比关系运算符、赋值运算符、条件运算符高。

4.9 sizeof运算符

  • sizeof(a)返回a所占字节数
  • 有两种使用方式,括号内可使用type或者expr。
    int a = 0;
    auto sz_a1 = sizeof(a);
    auto sz_a2 = sizeof(int);
    auto sz_a3 = sizeof a;
    // auto sz_a4 = sizeof int; 错误声明
  • sizeof的返回
    • char或char表达式:1
    • 引用类型:被引用类型所占的字节数
    • 指针:指针本身所占的字节数
    • 解引用指针:指针所指所占的字节数,指针不需要有效
    • 数组:整个数组所占空间的字节数,sizeof不会把数组转换成指针处理
    • string或vector:只返回固定部分的大小,不返回元素所占的空间。

4.10 逗号运算符

  • 对于左侧表达式,计算后将值丢掉,返回右侧表达式结果
int x=1,y=2;
a = ++x,++y; 
//x=2,y=3,a=3

4.11 类型转换

  • 隐式转换发生在:
    • 多数表达式中,比int小的整型,提升为较大的整数类型
    • 条件中,非布尔表达式转换为布尔表达式
    • 初始化过程中,初始值转换为变量类型;赋值中,右侧运算对象转换为左侧运算对象。
    • 算术运算、关系运算中多个类型需统一为一个类型
    • 函数调用时,实参转换为形参类型

4.11.1 算数转换

  • 整型提升
    • bool、char、signed char、unsigned char、short 、unsigned short 提升为int
    • 较大的char类型,如w_char、char16_t、char32_t转换到int、unsigned int、long、unsigned long、long long、unsigned long long中能容纳的最小类型
  • 当运算对象类型不一致,或含有无符号类型
    1.若运算对象都是符号数、或都是无符号数。则小类型提升为大类型。结束。
    2.若运算对象含有符号数和无符号数
    - 无符号数类型不小于带符号类型:带符号数转换为无符号数。int + unsigned int 都转为 unsigned int
    - 带符号数大于无符号数类型,转换结果依赖于机器。如果无符号类型的所有值都能存在该带符号类型中,则无符号类型转为带符号类型。如果不能,那么带符号类型的运算对象转换成无符号类型。如int和long的大小相同,long + unsigned int,long->unsigned int ;如果long类型占用的空间比int更多,则unsigned int->long

4.11.2 其他隐式转换

  • 在取地址符&、sizeof、decltype、typeid等运算符下,数组不会被转为指针。
  • 任意非常量指针都可以转为void*,任意指针都可以转换为const void*
  • 条件中非0值为真,否则为假

4.11.3 显式转换

  • 强制转换是非常危险的
  • 强制转换格式:cast-name<type>(expression)
  • cast-name有四种类型
    • dynamic_cast 在19.2节中介绍
    • static-cast:
      1.在明确转换成什么类型,不含底层const时使用
      2.将较大类型赋值给较小类型时,关闭了警告
      3.可用于找回void*指针的类型
void* p=&d;
//若类型不符合,会产生未定义的后果
double *dp =static_cast<double*>(p)
  • const_cast
    • 在取消底层const时使用
    • 不能使用const_cast来改变为其他类型
    • 如果对一个常量使用并写值,会出现未定义的后果
const char* pc;
//正确,但是通过p写值是未定义的行为
char *p =const_cast<char*>pc;
  • reinterpret_cast
    • 通常使用在为运算对象的位模式提供较低层次上的重新解释
    • static_cast只是可用在将大类型改为小类型,reinterpret_cast将数据类型直接改变。
    • reinterpret_cast本质依赖于机器,安全地使用他需要对编译器实现的转换过程非常了解。
int *ip;
char *pc = reinterpret_cast<char*>(ip);
  • 避免强制类型转换,即使必须使用也要记录假定,限制类型转换值作用域。

  • 旧式强制转换格式如下。替换合法,执行功能和static_cast、const_cast一致,替换不合法就和reinterpret_cast功能一致。

type(expr)
(type)expr
char *pc = (char*)ip;

4.12 运算符优先级表

在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值