C++ Primer 学习笔记 第四章 表达式(二)

位运算符

移位运算符(又叫 IO运算符)满足左结合律

移位运算符的优先级不高不低,介于中间:比算术运算符的优先级低,但比关系运算符、赋值运算符和条件运算符的优先级高。因此,一次使用多个运算符时,有必要在适当的地方加上括号使其满足我们的要求。

sizeof运算符

sizeof运算符返回一条表达式或一个类型名字所占的字节数。sizeof运算符满足右结合律,其所得的值是一个size_t 类型的常量表达式。运算符的对象有两种形式:
sizeof (type)
sizeof expr
在第二种形式中,sizeof返回的是表达式结果类型的大小,与众不同的一点是,sizeof并不实际计算其运算对象的值。
sizeof运算符的结果部分地依赖于其作用的类型:

  • char或者类型为char的表达式执行sizeof运算,结果得1.
  • 对引用类型执行sizeof运算得到被引用对象所占空间的大小。
  • 对指针执行sizeof运算得到指针本身所占空间的大小。
  • 对解引用指针执行sizeof运算得到指针指向的对象所占空间的大小,指针不需要有效。
  • 对数组执行sizeof运算得到整个数组所占空间的大小,等价于对数组中所有元素各执行一次sizeof运算并将所得结果求和。注意:sizeof运算不会把数组转换成指针来处理。
  • string对象或vector对象执行sizeof运算只返回该类型固定部分的大小,不会计算对象中的元素占用了多少空间。

逗号运算符

逗号运算符含有两个运算对象,按照从左向右的顺序依次求值
对于逗号运算符来说,首先对左侧表达式求值,然后将求值结果丢弃掉。逗号运算符真正的结果是右侧表达式的值。如果右侧运算对象是左值,那么最终求值结果也是左值。
逗号运算符经常用在for循环当中:

vector<int>::size_type cnt = ivec.size();
//将把size到1的值赋给ivec的元素
for( vector<int>::size_type ix = 0;
				  ix != ivec.size(); ++ix,--cnt )
	ivec[ix] = cnt;

这个循环在for语句的表达式中递增ix、递减cnt,每次循环迭代ixcnt相应改变 。只要ix满足条件,我们就把当前元素设成cnt的当前值。

类型转换

隐式转换(implicit conversion)
在下面这些情况下,编译器会自动地转换运算对象的类型:

  • 在大多数表达式中,比int类型小得整数值首先提升为较大的整数类型。
  • 在条件中,非布尔值转换成布尔类型。
  • 初始化过程中,初始值转换成变量的类型;在赋值语句中,右侧运算对象转换成左侧运算对象的类型。
  • 如果算术运算或关系运算的运算对象有多种类型,需要转换成同一种类型。
  • 函数调用时也会发生类型转换。

算术转换

  • 整型提升
  • 无符号类型的运算对象

其他类型的隐式转换

  • 数组转换成指针
  • 转换成布尔类型
  • 转换成常量
    允许将指向非常量类型的指针转换成指向相应常量类型的指针,对于引用也是这样。
    相反的转换并不存在,因为它试图删除底层const。
  • 类类型定义的转换
    例子:在条件部分读入istream:
string s, t = "a value";	//字符串字面值转换成string类型
while(cin >> s)				//while的条件部分把cin转换成布尔值

条件(cin >> s)读入cin的内容并将cin的值作为其求值结果。条件部分本来需要一个布尔类型的值,但是这里实际检查的是istream类型的值。幸好,IO库定义了从istream向布尔值转换的规则,根据这一规则,cin自动地转换成布尔值。所得的布尔值到底是什么由输入流的状态决定,如果最后一次读入成功,转换得到的布尔值是true;相反,如果最后一次读入不成功,转换得到的布尔值是false

显式转换

虽然有时不得不使用强制类型转换,但这种方法本质上是非常危险的。

命名的强制类型转换

一个命名的强制类型转换具有如下形式:
cast-name<type>(expression);
其中,type是转换的目标类型,expression是要转换的值。如果type是引用类型,则结果是左值。
cast-name指定了执行的是哪种转换。cast-namestatic_castdynamic_castconst_castreinterpret_cast中的一种。
dynamic_cast支持运行时类型识别,将在第19章有详细的介绍。

  • static_cast
    任何具有明确定义的类型转换,只要不包含底层const,都可以使用static_cast。例如,通过将一个运算对象强制转换成double类型就能使表达式执行浮点数除法:
//进行强制类型转换以便执行浮点数除法
double slope = static_cast<double>(j) / i;
  • const_cast
    const_cast只能改变运算对象的底层const。
const char *pc;
char *p = const_cast<char*>(pc);	//正确:但是通过p写值是未定义的行为

对于将常量对象转换成非常量的行为,我们一般称其为“去掉const性质(cast away the const)”。一旦我们去掉了某个对象的const性质,编译器就不在阻止我们对该对象进行写操作了。

建议:避免强制类型转换
强制类型转换干扰了正常的类型检查,因此,强烈建议程序员避免使用强制类型转换。

补充

  • 左值(lvalue)
    指那些求值结果为对象或函数的表达式。一个表示对象的非常量左值可以作为赋值运算符的左侧运算对象。
  • 右值(rvalue)
    指一种表达式,其结果是值而非值所在的位置。
  • 重载运算符(overloaded operator)
    针对某种运算符重新定义的适用于类类型的版本。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值