C++ 浅谈操作符的优先级和结合顺序
来源:互联网 发布:vb可以编写安卓软件 编辑:程序博客网 时间:2024/06/05 06:29
还是看 Primer,看到一个表达式,误认为它是错误的,没想到测试正确了。想一想,原来是自己没有想清楚。
题目:设 iter 为 容器 vector<string> 的一个迭代器,判断语句“ iter++->empty(); ” 是否非法。
思路一(错误):
-> 操作符 的 优先级比 后缀 ++ 要高,那么先调用 -> 操作符,但因为前面的 ‘+’ 非指针,判断非法。
思路二(正确):
的确是先调用 -> 操作符,但是它发现前面不是一个变量或字面量,而是 '+' ,故认定前面为一个表达式,由于 -> 操作符 是左结合的,因此先把表达式的结果算出来,然后再调用 -> 操作符。当且仅当前面表达式的结果是一个含有 empty() 成员函数的指针时,编译器才不会报错。。
进一步,-> 是左结合的,后缀 ++ 是右结合的。左结合的操作符会使用它左边的表达式作为自己的操作数,右结合的操作符会使用右边的表达式作为自己的操作数。在这个例子中, -> 的优先级比 后缀 ++ 高,率先执行。它发现,左边是一个表达式,然后就先算出表达式的值,作为自己的操作数。随后,就证明了这个语句是合法的。
对比以上两个思路,思路一忽略了操作符的结合顺序(associativity),只考虑了优先级(precedence)。而思路二则兼顾了两者。 得出结论:C++的优先级和结合顺序共同决定了表达式被 evaluate (求值) 的顺序。
下面讲一讲有关结合顺序的例子:
例1:
条件操作符 "cond ? expr1 : expr2" 是右结合的,给个例子:
string finalGrade = (grade > 90) ? "high pass" : (grade < 60) ? "fail" : "pass"
在这个例子中,条件操作符表达式 (grade < 60) ? "fail" : "pass" 会作为左边的条件操作符表达式的 operand。所以编译器求值(evaluate)的顺序,应当和下面这条语句等价:
string finalGrade = (grade > 90) ? "high pass" : ((grade < 60) ? "fail" : "pass")
然而,条件操作符是比较特殊的,虽然右结合,但是它却可以提前判断条件是否满足,从而选择是否 evaluate 右边的表达式。因为如果条件满足了,那根本就不需要去evaluate 右边的表达式了,也避免了无谓的操作。
所以,条件操作符的右结合可以说是一个例外。但是对于其他的“不能预判”的右结合的操作符,还是要按正常右结合的顺序来 evaluate 的,也就是说还是要和打上括号后的表达式有一样的 evaluate 顺序。
例二:
cout 重载的 << 操作符是左结合的。所以下面两条语句的 evaluate 顺序是一样的。
cout << a << b;
(cout << a) << b;
最后,献上 Primer 里对应chapter的summary的一句话:
"Precedence determines how operators are grouped in a compound expression. Associativity determines how operators at the same precedence level are grouped."
References
[1] 《C++ Primer Fifth Edition》 Stanley B. Lippman, Josée Lajoie, Barbara E. Moo
- C++ 浅谈操作符的优先级和结合顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 浅谈C/C++中运算符的优先级、运算符的结合性以及操作数的求值顺序
- 关于C/C++种运算符的优先级,结合性以及操作数的求值顺序
- C/C++中操作符的优先级和求值顺序
- C/C++中操作符的优先级和求值顺序
- 操作符的优先级和结合性
- C 语言操作符优先级和结合性
- C语言中操作符的优先级和结合性的区别
- C操作符优先级、结合性
- C语言中的操作符优先级和求值顺序
- 操作符的优先级 运算符的结合性 操作符的计算顺序
- Java操作符的优先级和结合性
- Java操作符的优先级和结合性
- 关于css的背景和列表属性
- 关于css的定位属性
- 使用ARM DS-5与Dstream StreamLine进行Android底层性能分析的一个实例
- 关于css的float,overflow及z-index属性
- JavaScript与html的结合方式
- C++ 浅谈操作符的优先级和结合顺序
- Android LayoutInflater的inflate方法中attachToRoot的作用
- JavaScript的数据类型,运算符及数据类型之间的转化
- android-percent-support-extend
- 关于JavaScript的函数定义及调用
- 关于JavaScript的函数劫持
- MySQL中group_concat函数深入理解
- 关于JavaScript的几种常见的全局函数
- 关于JavaScript的数组