首页 » 技术分享 » C++ 右结合律与左结合律详解

C++ 右结合律与左结合律详解

 

     运算符的结合性是指相同优先级的运算符在同一个表达式中,且没有括号的时候,运算符和操作数的结合方式,通常有从左到右结合和从右到左结合两种方式。

     举个例子,假设~是一个运算符,又有表达式a~b~c,如果~是左结合的,那么该表达式被解析为(a~b)~c,如果~是右结合的,那么该表达式将被解析为a~(b~c)。比如上表中三目运算符?:是从右向左结合的

那么下面的表达式a > b ? b > c ? 1 : 0 : 2将被解析为 a > b ? (b > c ? 1 : 0) : 2。

再看下运算符的优先级和结合律:

// C++ Operator Precedence and Associativity
// The highest precedence level is at the top of the table.
//+------------------+-----------------------------------------+---------------+
//| Operator         | Name or Meaning                         | Associativity |
//+------------------+-----------------------------------------+---------------+
//| ::               | Scope resolution                        | None          |
//| ::               | Global                                  | None          |
//| [ ]              | Array subscript                         | Left to right |
//| ( )              | Function call                           | Left to right |
//| ( )              | Conversion                              | None          |
//| .                | Member selection (object)               | Left to right |
//| ->               | Member selection (pointer)              | Left to right |
//| ++               | Postfix increment                       | None          |
//| --               | Postfix decrement                       | None          |
//| new              | Allocate object                         | None          |
//| delete           | Deallocate object                       | None          |
//| delete[ ]        | Deallocate object                       | None          |
//| ++               | Prefix increment                        | None          |
//| --               | Prefix decrement                        | None          |
//| *                | Dereference                             | None          |
//| &                | Address-of                              | None          |
//| +                | Unary plus                              | None          |
//| -                | Arithmetic negation (unary)             | None          |
//| !                | Logical NOT                             | None          |
//| ~                | Bitwise complement                      | None          |
//| sizeof           | Size of object                          | None          |
//| sizeof ( )       | Size of type                            | None          |
//| typeid( )        | type name                               | None          |
//| (type)           | Type cast (conversion)                  | Right to left |
//| const_cast       | Type cast (conversion)                  | None          |
//| dynamic_cast     | Type cast (conversion)                  | None          |
//| reinterpret_cast | Type cast (conversion)                  | None          |
//| static_cast      | Type cast (conversion)                  | None          |
//| .*               | Apply pointer to class member (objects) | Left to right |
//| ->*              | Dereference pointer to class member     | Left to right |
//| *                | Multiplication                          | Left to right |
//| /                | Division                                | Left to right |
//| %                | Remainder (modulus)                     | Left to right |
//| +                | Addition                                | Left to right |
//| -                | Subtraction                             | Left to right |
//| <<               | Left shift                              | Left to right |
//| >>               | Right shift                             | Left to right |
//| <                | Less than                               | Left to right |
//| >                | Greater than                            | Left to right |
//| <=               | Less than or equal to                   | Left to right |
//| >=               | Greater than or equal to                | Left to right |
//| ==               | Equality                                | Left to right |
//| !=               | Inequality                              | Left to right |
//| &                | Bitwise AND                             | Left to right |
//| ^                | Bitwise exclusive OR                    | Left to right |
//| |                | Bitwise OR                              | Left to right |
//| &&               | Logical AND                             | Left to right |
//| ||               | Logical OR                              | Left to right |
//| e1?e2:e3         | Conditional                             | Right to left |
//| =                | Assignment                              | Right to left |
//| *=               | Multiplication assignment               | Right to left |
//| /=               | Division assignment                     | Right to left |
//| %=               | Modulus assignment                      | Right to left |
//| +=               | Addition assignment                     | Right to left |
//| -=               | Subtraction assignment                  | Right to left |
//| <<=              | Left-shift assignment                   | Right to left |
//| >>=              | Right-shift assignment                  | Right to left |
//| &=               | Bitwise AND assignment                  | Right to left |
//| |=               | Bitwise inclusive OR assignment         | Right to left |
//| ^=               | Bitwise exclusive OR assignment         | Right to left |
//| ,                | Comma                                   | Left to right |
//+------------------+-----------------------------------------+---------------+


有个需要注意的地方:数组解析和解引用与递增运算符混用

/***************************************************************************
 *  @file       main.cpp
 *  @author     MISAYAONE
 *  @date       17  March 2017
 *  @remark     17  March 2017 
 ***************************************************************************/

#include <iostream>
#include <vector>
#include <list>
#include <string>
using namespace std;

int main(int argc,char** argv)
{
	//*(解引用)运算符优先级优于+(加号)运算符
	int a[3][3] = {1,3,5,7,9,11,13,15,17};
	cout<<"a[2]+1:"<<a[2]+1<<endl;//生成a[2][1]的地址,二维数组中a[2]代表一个一维数组的首地址
	cout<<"*a[2]+1:"<<*a[2]+1<<endl;//先对a[2][0]取值,再加1
	cout<<"*(a[2]+1):"<<*(a[2]+1)<<endl;//生成a[2][1]的地址,再取值
	cout<<"(*a[2])+1:"<<(*a[2])+1<<endl;//先对a[2][0]取值,再加1

	//*(解引用)运算符优先级与+(一元正号)运算符相同,皆为右结合律
	cout<<"+*a[2]:"<<+*a[2]<<endl;


	//*(解引用)运算符的优先级低于后置递增运算符(++),但是结果为1
	//这是一个坑点,因为后置++返回的是原对象的副本,并不会将其递增的结果返回
	int c[3]= {1,3,5};
	vector<int> b(c,c+3);
	auto p = b.begin();
	cout<<"*p++:"<<*p++<<endl;

	cin.get();
	return 0;
}

自己写代码搞不清楚算符优先级请多加括号,但是一般这样的问题都会出现于笔试题或者面试题中,所以还是弄清楚比较好,注意上面代码的两个小坑~


转载自原文链接, 如需删除请联系管理员。

原文链接:C++ 右结合律与左结合律详解,转载请注明来源!

0