原创 【博客大赛】《C++ Primer》学习笔记(十三)操作符和操作数

2016-3-17 11:20 800 13 15 分类: MCU/ 嵌入式 文集: Qt和Cpp


到这里,前三章的内容就学习完成了。
现在我们已经知道了怎么创建C++程序、怎么使用变量和修饰符、怎么使用strings和vector。
接下来该学习操作符和操作数了。

对于接触过C语言的人来说,操作符和操作数并不陌生。
但是它们对于C++的意义不止与此,其中一个很重要的概念就是操作符重载。

每一个表达式,要么是rvalue,要么是lvalue。
一般来说,我们使用rvalue时,使用的是它的值;使用lvalue时,使用的是它的地址。

之前学习过的decltype,括号内是变量还是表达式就有区别:
decltype((i))
decltype(a = b)
decltype(i)

当我们使用一个表达式来作为decltype的参数时,它返回的是lvalue的引用。
所以decltype((i))返回的是int&,decltype(a = b)返回的是int&。
如果p是一个int*的指针,则decltype(*p)返回的是int&。
如果p是一个int*的指针,则decltype(&p)返回的是int**。

另外,这本书里有个bug:
6 + 3 * 4 / 2 + 2
值是14,不是20!!!

这里我们并不知道这两个函数哪个先被执行:
int i = f1() * f2();
所以这两个函数的执行就不要有相互依赖的关系了,否则执行的结果是不确定的。

----------------
有关商和余数的符号问题……
以后在实际应用的时候慢慢调试吧。

----------------
不要使用true或者false来对一个操作数做比较,比如:
int val = /* ? */;
if (val == true)
    cout << val << endl;
这是因为true会被转换成val的类型,此类型之间的比较可能会偏离程序本来的意图。

----------------
尽可能的使用++i,而不是i++。
用惯C语言的人可能很奇怪,为什么要这样做。这是因为后者会产生一个temp,从而需要更多步骤。
尤其在对迭代器进行操作的情况下,耗费的资源更多。因此还是尽量使用prefix。

----------------
sizeof操作符会返回以字节为单位的大小,数据类型是size_t。
sizeof (type)
sizeof expr

前者返回数据类型的大小,后者返回表达式的大小。
Sales_data data, *p;
int ia[10];
sizeof(Sales_data);  //Sales_data所需空间大小
sizeof data;         //Sales_data所需空间大小
sizeof p;            //指针的大小
sizeof *p;           //Sales_data所需空间大小
sizeof data.revenue; //Sales_data的成员revenue所需空间大小
sizeof Sales_data::revenue; //同上
sizeof ia;           //数组大小,不是指针大小

sizeof返回的是个常量:
constexpr size_t sz = sizeof(ia) / sizeof(*ia);
int arr2[sz];

----------------
隐式类型转换的时候会发生什么?
 • 大部分的表达式里,小于int的类型会被转换成int;
 • 在条件判断里,非boot的表达式会被转换成bool;
 • 初始化的时候,初始值会被转换成变量类型,赋值时右操作数会被转换成左操作数;
 • 在算术和关系运算中,混合的操作数会被转换成common类型;
 • 函数调用时也会发生自动类型转换。

显式类型转换的时候会发生什么?
static_cast
它经常用在使用大的数据类型给小的数据类型赋值时,它告诉程序员和编译器,精度的损失无关紧要。
如果不使用它,编译器可能会发生警告;使用它,则声明警告是已知的。
double slope = static_cast<double>(j) / i;
void *p = &d;
double *dp = static_cast<double*>(p);

const_cast
它可以把被const修饰的对象转换成非const的,实际上也只有它可以。
虽然编译器会允许我们往这样的变量里写入,但是会发生什么是不确定的。
const char *cp;
char *q = static_cast<char*>(cp);
static_cast<string>(cp);   //正确,static_cast可以用来进行类型转换
const_cast<string>(cp);    //错误,const_cast只能用来转换const

reinterpret_cast
它可以重新对对象进行解释。
int *ip;
char *pc = reinterpret_cast<char*>(ip);
实际的对象仍然是int,因此把它当char使用语法没问题,但是功能有问题。这也说明它是非常危险的。
所以除非我们确信需要,并且明白它干了什么,否则就不要使用它了。

dynamic_cast
以后再解释。

----------------
第四章的内容,有关操作符和操作数到这里就学习完毕。
它有很多和C语言重复的内容,所以可能会看得非常无聊!
Anyway,实际使用的时候还会回过头来进行练习。现在进行下一章吧。

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

DiracFatCat 2016-3-19 13:11

哈哈,再一起来一次吧~

东莞元宝代理Microchip长电二三极管 2016-3-18 08:16

变量与表达式!好熟悉啊!20年前学过一点皮毛!
相关推荐阅读
DiracFatCat 2018-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,但是由于...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
EE直播间
更多
我要评论
2
13
关闭 站长推荐上一条 /3 下一条