- 一元,二元,三元和函数都是运算符
- 表达式的理解有三个方面
- 优先级
precedence
- 结合律
associativity
- 运算对象的求值顺序
order of evalution
- 优先级
- 左值和右值
- 右值(在
vs
中开启/W4
警告)不能取地址
string a = "Hello World!"; string b = "121"; string c = a + b; // 报错,不能取右值的地址 string* d = &(a + b); // 引用右值必须增加const修饰符,或者c++11的右值引用 const string& e = a + b; // 报错,不能取右值的地址 string * f= &string("abc");
- 右值(在
- 优先级和结合律和括号决定了运算对象的组合的方式
- 求值顺序
- 如下的程序未规定求值顺序
// f1和f2一定会在*乘法之前调用,但是不知道f1和f2之间调用的优先级顺序 int i =f1()*f2(); // 对于没有指定求值顺序的运算符来说,如果表达式指向并且修改了同一个对象,将引发错误并产生未定义的行为
- 有四种运算符明确规定了运算对象的求值顺序。
&&
和||
和?:
和,
- 求值顺序和优先级和结合律无关,大多数二元运算符都没有规定求值顺序,这样给编译器优化留下了相当大的空间。而
java
则强制规定求值顺序从左到右边
// 调用顺序没有明确规定 f()+g()*h()+j();
- 逻辑和关系运算符产生的结果都是右值
- 赋值运算符
- 左侧必须是可修改的左值
- 满足右结合律
- 复合赋值运算符比普通运算符少求值一次,复合运算符只用运算一次
- 解引用运算符的优先级低于点运算符,所以如果不用箭头运算符,需要在解引用处加括号
- 解引用运算符表达式的结果一定是一个左值
struct A{ int a; int b(){ return 1; } }; A a; A * ptr=&a; // 结果是左值 ptr->a; // 结果并非左值,因为这个表达式后面是()括号运算符而非单纯的解引用运算符 ptr->b();
- 点运算符如果成员所属对象是左值,那么结果是左值。如果成员所属对象是右值,那么结果是右值
- 条件运算符两个表达式都是左值或者能转换成同一种左值类型时,运算结果猜时左值,否则运算的结果时右值,条件运算符满足右结合性。三目运算符的优先级很低
// 这里就是看c的左边三目(冒号)和右边的三目(问号)之间的优先级,根据右结合性,可知时先执行c的判断 a?b:c?d:e
- 左移运算符在负数符号数中是未定义的行为。负数右移是实现定义的(大多数平台实现的是保留符号位右移)。
c++20
起负数位移全部有意义且非实现定义 sizeof
运算符返回一个表达式或一个类型名字所占的字节(注意是字节数而不是位)数。满足右结合律,和一元*
运算符的优先级一样。返回的类型是size_t
的常量表达式。sizeof(type)
sizeof expr
表达式结果的大小并且sizeof
就像decltype
一样不实际计算其运行对象的值
// p是未初始化指针,在sizeof条件下依然安全 sizeof *p; // c++11 sizeof可以通过作用域运算符来获取类的成员的大小 sizeof Class::field
sizeof
对数组来说是整个数组所占空间的大小。等价于对所有元素各执行一次sizeof
来求和。注意sizeof
不会把数组转换成指针string
或者vector
等对象执行sizeof
只回返回类型固定部分的大小,不会计算对象中的元素占用了多少空间sizeof
返回的结果是常量表达式
- 算术运算符,
+ - * / %
以及一元+ -
- 运算符优先级
c++表达式
最新推荐文章于 2021-12-13 09:45:32 发布