c++表达式(原创)

  • Post author:
  • Post category:其他


接着前面的内容,我们继续学习。乘风破浪会有时,直挂云帆济沧海!加油

1、c++定义了一元和二元运算符。

2、关于左值和右值(c++表达式可以分为左值和右值):

(1)左值可以在赋值语句的左侧(用的是内存地址)和右侧(用的是内容);

(2)右值只能在赋值语句的右侧(用的是内容);

(3)左值分配有内存空间而右值则没有分配。

3、使用关键字decltype时,左值和右值有所不同:

(1)decltype作用于表达式生成左值;

(2)取地址运算符生成右值,解引用运算符生成左值;

int *p;
decltype(*p);//结果是:int & ---解引用运算符得到的是个左值(对象),decltype作用于左值返回一个引用类型 i
decltype(&p);//结果是:int**--取址运算符得到的是个右值(地址),decltype作用于右值返回一个右值

4、对于那些没有指定执行顺序的运算符来说,如果表达式指向并修改了同一个对象,将会产生未定义的行为。

int i = 0;
cout << i << " " << ++i << endl;//产生未定义的行为因为<<没有定义执行顺序

5、有4种运算符明确规定了运算对象的求职顺序。

(1)&&:规定先求左侧对象的值(只有左侧为真才求右侧的值)

(2)||:只有左侧为假才求右侧值

6、关于正确处理表达式的建议:

(1)、拿不准的时候使用括号

(2)、在一个表达式中不要对同一对象进行操作(例外:*++iter当改变运算对象的字表达式是另外一个表达式的运算对象)

7、只有整数才能进行取余运算。

8、关系运算符作用于算术类型和指针类型,逻辑运算符作用于能转换为bool类型的类型,这两类运算符的运算对象和结果都是左值。

9、关系运算符满足左结合律

10、执行赋值运算符不能进行窄化转换

11、赋值运算符满足右结合律

12、因为赋值运算符的优先级低于关系运算符,所以条件语句中赋值部分应该加上括号。

13、递增和递减运算符(除非必须,否则不要使用递增和递减运算符):

(1)前置++/–:执行递增/递减操作,返回最新的值

(2)后置++/–:执行递增/递减操作,返回原来的副本

14、后置递增的优先级高于解引用运算符(*++iterator)

15、解引用运算符的优先级低于点运算符((*p).size())

16、箭头运算符作用于一个指针类型的对象返回一个左值,点运算符依赖与成员的对象

17、条件运算符满足右结合律,条件运算符的嵌套最好不要超过三层。

finalgrade = (grade > 90 ) ? "high pass"
                           : (grade < 60) ? "pass";

18、位运算符作用于整数类型的运算对象,并把运算对象看成是二进制位的集合。

19、建议将位运算符作用于无符号类型,位求反运算符(~)将对象逐位求反返回一个新的值。

20、移位运算符的优先级比运算符的优先级低,比关系运算符、赋值运算符合条件运算符的优先级高。

21、sizeof运算符:返回一个表达式或一个类型名字所占的字节数(size_t类型),满足右结合律。

22、sizeof的运算结果部分依赖于其作用的类型:

  • 对char或者类型为char的表达式执行sizeof,结果为1
  • 对引用类型执行得到引用对象所占空间的大小
  • 对指针执行得到指针本身所占的大小
  • 对解引用指针执行,得到指向对象的空间大小
  • 对数组执行得到真个数组的大小
  • 对string和vector执行得到该类型固定部分的大小

23、逗号表达式:首先求左侧表达式的值,然后将结果丢掉求右侧表达式的值。逗号表达式的真正结果是右侧表达式的值。

24、隐式类型的转换:

  • 比int小的整数值首先提升为较大的整数类型
  • 非布尔值转换为布尔值
  • 赋值语句中,右侧对象被转换为左侧对象
  • 算术运算和关系运算的运算对象有多种类型,需要转换为一种类型

25、算术转换:把一种算术类型转换为另外一种算术类型。

26、整形提升:把小的整数类型转换为大的整数类型

27、数组转换为指针:大多数时,数组自动转换为指向数组首元素的指针

28、当数组被用作decltype的参数,或者作为去地址(&)、sizeof、typeid等运算符的对象时上面的转换不会发生。

29、指针的转换:常量整数值0或者字

面值nullptr能转换为任意指针类型,任意指针类型可以转换为void*,void*可以转换为const  void*.

30、  显示转换:命名的强制类型转换 –cast-name<type>(expression),type转换的目标类型,expression是要转换的值。如果type是引用类型,则结果是左值。cast-name是static_cast,dynamic_cast,const_cast和reinterpret_cast中的一种。

31、static_cast任何具有明确定义的转换,只要不包含底层const(指向常量的指针),都可以使用static_cast。

int a =23;
int const * p = &a;//底层的const  指向常量的指针
//-----------------------------
int *const p = &b;//顶层const     指向对象的常量指针
//--------------------------------
double slope = static_cast<double>(j);

31、const_cast只能改变运算对象的底层const

const char * pc;//底层的const 指向常量的指针
char * = const_cast<char*>pc;

32、reinterpret_cast:为运算对象的位模式提供较低层次上的重新解释。

33、尽量避免强制类型转换。




版权声明:本文为weixin_42182348原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。