# 2.1、运算符
## 运算符分类
根据运算符接受的参数个数可以将运算符分为**单元运算符(unary operators)**和**双元运算符(binary operators)**。
根据运算符功能可以将运算符分为**算术运算符(arithmetic operators)**、**关系运算符(relational operators)**、**逻辑运算符(logical operators)**、**位运算符(bitwise operators)**、**赋值运算符(assignment operators)** 和其他运算符,其中其他运算符包括:**自增自减运算符(increment and decrement operators)**、**成员访问运算符(member access operators)**、**条件运算符(conditional operator)**、**sizeof 运算符**、**逗号运算符(comma operator)**、**指针运算符(pointer operators)**。
[Reference: runoob-C++运算符](https://www.runoob.com/cplusplus/cpp-operators.html)
> `sizeof` 运算符在编译期间即确定对象占用内存的大小,所以其值是一个常量。
## 运算符优先级和结合性
一个表达式包含多个运算则是一个组合表达式,运算符的优先级(precedence)和结合性(associativity)将决定其最终结果。
| 类别 | 运算符 | 结合性 |
| --- | --- | --- |
| 后缀 | () \[\] -> . ++ - - | 从左到右 |
| 一元 | \+ - ! ~ ++ - - (type)\* & sizeof | 从右到左 |
| 乘除 | \* / % | 从左到右 |
| 加减 | \+ - | 从左到右 |
| 移位 | > | 从左到右 |
| 关系 | >= | 从左到右 |
| 相等 | \== != | 从左到右 |
| 位与 AND | & | 从左到右 |
| 位异或 XOR | ^ | 从左到右 |
| 位或 OR | \| | 从左到右 |
| 逻辑与 AND | && | 从左到右 |
| 逻辑或 OR | \|\| | 从左到右 |
| 条件 | ?: | 从右到左 |
| 赋值 | \= += -= \*= /= %=>>= <<= &= ^= \|= | 从右到左 |
| 逗号 | , | 从左到右 |
## 短路计算
**短路计算**(short-circuit evaluation):对于逻辑运算符 `&&` 和 `||`,在某种情况下左值确定时最终结果就已经确定,这个时候将不在进行右值计算。
* The right side of an `&&` is evaluated if and only if the left side is true
* The right side of an `||` is evaluated if and only if the left side is false
## 自增自减操作的前后缀形式
**区别**
* `++i` 先执行自增操作,再返回值;`i++` 先返回值,再对 `i` 进行自增操作;
* `i++` 需要先把旧值保存,多了一次变量赋值操作,所以 `++i` 的效率要高于 `i++`;
* `i++` 不能作为左值,而 `++i` 可以 ;
**实现**
```c++
// 前缀形式:
int& int::operator++() { // 函数返回值为一个引用形式,既可以作为一个左值使用
*this += 1; // 增加
return *this; // 取回值
}
//后缀形式:
const int int::operator++(int) { // 函数返回值是一个非左值型的
int oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}
```
## 运算符重载
**运算符重载(overloaded operators)** 指对已有的运算符重新进行定义,赋予其另外一种功能,以适应不同的数据类型。
``` c++
class NewInt {
public:
explicit NewInt(int data) : data(data) {}
NewInt operator+(const NewInt& rhs) {
return NewInt(data + rhs.data);
}
int data;
};
NewInt operator+ (const NewInt& lhs, const int& rhs) {
return NewInt(lhs.data + rhs);
}
int main () {
NewInt a(1);
NewInt b(2);
NewInt c = a + b; // equals c = a.operator+(b);
NewInt d = a + 3; // equals d = operator+(a, 3);
return 0;
}
```
**如何重载自增运算符**:C++规定,在重载`++`或`--`时,允许写一个增加了无用 int 类型形参的版本,编译器处理`++`或`--`前置的表达式时,调用参数个数正常的重载函数;处理后置表达式时,调用多出一个参数的重载函数。
``` c++
NewInt& operator++(); //用于前置形式
NewInt operator++(int); //用于后置形式
```
c++重载运算符时返回值为类的对象是为了实现连续的运算,而返回对象的引用则是为了避免在连续运算过程中重复拷贝对象,以提升线效率。
- 目录
- 基础知识
- 1、变量和基础类型
- 1.1、内置类型
- 1.2、变量
- 1.3、复合类型
- 1.4、类型修饰符
- 1.5、类型处理
- 1.6、自定义结构
- 1.7、数组
- 2、表达式和语句
- 2.1、运算符
- 2.2、语句
- 3、函数
- 1、语法相关
- 2、资源管理
- 3、面向对象
- 4、模板与泛型编程
- Problem01:判断类中是否包含函数
- Problem02:解析函数的参数类型
- 5、系统库
- Problem01:多线程维护最大值
- Problem02:介绍一下strcpy、strncpy、memcpy、memmove
- Problem03:介绍一下网络编程
- Problem04:select、poll、epoll的区别
- 未整理
- Problem11:实现在main函数前、后执行的函数
- Problem12:可变参函数的实现
- Problem13:全局变量初始化顺序问题
- Problem14:介绍一下隐式转换
- Problem07:实现一个不能被拷贝的类
- Problem08:实现一个只能通过动态、静态分配的类
- 开源项目
- redis
- 第一部分 数据结构与对象
- redis 底层数据结构
- redis 对象
- taskflow
- 数据结构
- Executor
