# 运算符 ## 补码运算符 ```c++ int x = 1; int y = ~x; std::cout << y; //输出254 ``` ## ++操作符 ```c++ int a = 4; int b = a++; int c = 4; int d = ++c; ``` ++运算符放放在前面还是后面结果是一样的,但是需要注意的细节就是在 `i++` 计算时会用到临时的中间变量,会占用运行时的内存,而 ++i 则不会使用临时的中间变量,程序运行的内存上不变。所以可以尽量使用 ++i 而不是 i++ 的形式。 ## C++不能重载的操作符 ```c++ (1) "."(类成员访问运算符) (2)" .*"(类成员指针访问运算符) (3) "::"(域运算符) (4)"sizeof"(长度运算符) (5) " ?:"(条件运算符/三目运算符) (6) dynamic_cast (7) static_cast (8) reinterpret_cast (9) const_cast (10) typeid(获取类型信息) ``` ## 运算符重载后,优先级和结合性怎么办? 用户重载新定义运算符,不改变元运算符的优先级和结合性。这就是说,对运算符重载不改变运算的优先级和结合性,并且运算符重载后,也不改变运算符的语法结构,即单目运算符的语法结构只能冲仔尾单目运算符,双目运算符只能重载为双目运算符。 ## 编译程序如何选用那一个运算符函数? 运算符重载实际是一个函数,所以运算符的重载实际上是函数的重载。编译程序对运算符重载的选择,遵循着函数重载的算则原则。当遇到不很明显的运算时,编译程序将去寻找参数相匹配的运算符函数。 ## 重载你算符有哪些限制? 不可臆造新的运算符。必须把重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中。 重载运算符坚持4个“不能改变” 不能改变运算符操作数的个数; 不能改变运算符原有的优先级; 不能改变运算符原有的结核性; 不能改变运算符原有的语法结构。 ## 运算符重载时必须遵循哪些原则? 运算符重载可以是程序更加简洁,是表达式更加直观,增加可读性。但是运算符重载使用不宜过多,否则会带来一定麻烦。使用重载运算符是应遵循如下原则: - 重载运算符含义必须清楚 - 重载运算符不能有二义性 ## 运算符及其优先级 > 运算符优先级顺口溜: > 淡云一笔,鞍落三服 > > 1. 淡:单目运算符 > 2. 云:算法运算符 > 3. 一:移位运算符 > 4. 笔:比较运算法 > 5. 鞍:按位运算符 > 6. 落:逻辑运算符 > 7. 三:三目运算符 > 8. 服:赋值运算符 | 优先级 | 运算符 | 简述 | 示例 | 重载性 | 结合性 | | ------ | ------------------ | ------------------------------ | ---------------------------------------------------- | ------ | -------- | | 1 | `::` | 作用域解析(C++专有) | Class::age = 2; | 否 | 由左至右 | | 2 | `++` | 后缀递增 | | | | | | `--` | 后缀递减 | | | | | | `{}` | 组合 | {i++;a*=i;} | | | | | `()` | 函数调用或变量初始化 | c_tor(int x, int y) : _x(x), _y(y * 10) {} | | | | | `[]` | 数组访问 | array[4] = 2; | | | | | `.` | 以对象方式访问成员 | obj.age = 34; | 否 | | | | `->` | 以指针方式访问成员 | ptr->age = 34; | | | | | `dynamic_cast` | 运行时检查类型转换(C++专有) | Y& y = dynamic_cast(x); | 否 | | | | `static_cast` | 未经检查的类型转换(C++专有) | Y& y = static_cast(x); | 否 | | | | `reinterpret_cast` | 重定义类型转换(C++专有) | int const* p = reinterpret_cast(0x1234); | 否 | | | | `const_cast` | 更改非常量属性(C++专有) | int* q = const_cast§; | 否 | | | | `typeid` | 获取类型信息(C++专有) | std::type_info const& t = typeid(x); | 否 | | | 3 | `++` | 前缀递增 | ++i | | | | | `--` | 前缀递减 | –i | | | | | `+` | 一元正号 | int i = +1; | | | | | `-` | 一元负号 | int i = -1; | | | | | `!` ` not` | 逻辑非 `!`的备用拼写 | if (!done) … | | | | | `~` `compl` | 按位取反 `~`的备用拼写 | flag1 = ~flag2; | | | | | `(*type*)` | 强制类型转换 | int i = (int)floatNum; | | | | | `*` | 取指针指向的值 | int data = *intPtr; | | | | | `&` | 取变量的地址 | int *intPtr = &data; | | | | | `sizeof` | 某某的大小 | size_t s = sizeof(int); | 否 | | | | `new` | 动态内存分配(C++专有) | long* pVar = new long; | | | | | `new[]` | 动态数组内存分配(C++专有) | long* array = new long[20]; | | | | | `delete` | 动态内存释放(C++专有) | delete pVar; | | | | | `delete[]` | 动态数组内存释放(C++专有) | delete [] array; | | | | 4 | `.*` | 成员对象选择(C++专有) | obj.*var = 24; | 否 | 由左至右 | | | `->*` | 成员指针选择(C++专有) | ptr->*var = 24; | | | | 5 | `*` | 乘法 | int i = 2 * 4; | | | | | `/` | 除法 | float f = 10.0 / 3.0; | | | | | `%` | 模数(取余) | int rem = 4 % 3; | | | | 6 | `+` | 加法 | int i = 2 + 3; | | | | | `-` | 减法 | int i = 5 - 1; | | | | 7 | `<<` | 比特左移 | int flags = 33 << 1; | | | | | `>>` | 比特右移 | int flags = 33 >> 1; | | | | 8 | `<` | 小于关系 | if (i < 42) … | | | | | `<=` | 小于等于关系 | if (i <= 42) … | | | | | `>` | 大于关系 | if (i > 42) … | | | | | `>=` | 大于等于关系 | if (i >= 42) … | | | | 9 | `==` `eq` | 等于关系 `==`的备用拼写 | if (i == 42) … | | | | | `!=` `not_eq` | 不等于关系 `!=`的备用拼写 | if (i != 42) … | | | | 10 | `&` `bitand` | 比特 AND `&`的备用拼写 | flag1 = flag2 & 42; | | | | 11 | `^` `xor` | 比特 XOR(独占or) `^`的备用拼写 | flag1 = flag2 ^ 42; | | | | 12 | `|` `bitor` | 比特 OR(包含or) `|`的备用拼写 | flag1 = flag2 \| 42; | | | | 13 | `&&` `and` | 逻辑 AND `&&`的备用拼写 | if (conditionA && conditionB) … | | | | 14 | `||` `or` | 逻辑 OR `||`的备用拼写 | if (conditionA \|\| conditionB) … | | | | 15 | `*c*?*t*:*f*` | 三元条件运算 | int i = a > b ? a : b; | 否 | 由右至左 | | 16 | `=` | 直接赋值 | int a = b; | | | | | `+=` | 以和赋值 | a += 3; | | | | | `-=` | 以差赋值 | b -= 4; | | | | | `*=` | 以乘赋值 | a *= 5; | | | | | `/=` | 以除赋值 | a /= 2; | | | | | `%=` | 以取余数赋值 | a %= 3; | | | | | `<<=` | 以比特左移赋值 | flags <<= 2; | | | | | `>>=` | 以比特右移赋值 | flags >>= 2; | | | | | `&=` `and_eq` | 以比特AND赋值 `&=`的备用拼写 | flags &= new_flags; | | | | | `^=` `xor_eq` | 以比特XOR赋值 `^=`的备用拼写 | flags ^= new_flags; | | | | | `|=` `or_eq` | 以比特OR赋值 `|=`的备用拼写 | flags \|= new_flags; | | | | 17 | `throw` | 抛出异常 | throw EClass(“Message”); | 否 | | | 18 | `,` | 逗号运算符 | for (i = 0, j = 0; i < 10; i++, j++) … | | 由左至右 |