## 例题
- [LOJ6515「\[雅礼集训 2018 Day10\] 贪玩蓝月」](https://loj.ac/problem/6515)
+ [LOJ6515「\[雅礼集训 2018 Day10\]贪玩蓝月」](https://loj.ac/problem/6515)
> 一个双端队列(deque),m 个事件:
>
## C++ 标准
-首先需要介绍的是 C++ 本身的版本。由于 C++ 本身只是一门语言,而不同的编译器对 C++ 的实现方法各不一致,因此需要标准化来约束编译器的实现,使得 C++ 代码在不同的编译器下表现一致。C++ 自1985年诞生以来,一共由国际标准化组织( ISO )发布了 5 个正式的 C++ 标准,依次为 C++98、C++03、C++11 (亦称 C++0x)、C++14 (亦称 C++1y)、C++17 (亦称 C++1z),最新的标准 C++20 仍在制定中。此外还有一些补充标准,例如 C++ TR1。
+首先需要介绍的是 C++ 本身的版本。由于 C++ 本身只是一门语言,而不同的编译器对 C++ 的实现方法各不一致,因此需要标准化来约束编译器的实现,使得 C++ 代码在不同的编译器下表现一致。C++ 自 1985 年诞生以来,一共由国际标准化组织(ISO)发布了 5 个正式的 C++ 标准,依次为 C++98、C++03、C++11(亦称 C++0x)、C++14(亦称 C++1y)、C++17(亦称 C++1z),最新的标准 C++20 仍在制定中。此外还有一些补充标准,例如 C++ TR1。
每一个版本的 C++ 标准不仅规定了 C++ 的语法、语言特性,还规定了一套 C++ 内置库的实现规范,这个库便是 C++ 标准库。C++ 标准库中包含大量常用代码的实现,如输入输出、基本数据结构、内存管理、多线程支持等。掌握 C++ 标准库是编写更现代的 C++ 代码必要的一步。C++ 标准库的详细文档在 [cppreference](https://zh.cppreference.com/) 网站上,文档对标准库中的类型函数的用法、效率、注意事项等都有介绍,请善用。
-需要指出的是,不同的 OJ 平台对 C++ 版本均不相同,例如[最新的 ACM 比赛规则](https://icpc.baylor.edu/worldfinals/programming-environment)支持 C++14 标准,而 [NOI 现行规则](http://www.noi.cn/newsview.html?id=559&hash=E4E249) 中指定的 g++ 4.8 [默认支持标准](https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Standards.html#Standards)是 C++98。因此在学习 C++ 时要注意比赛支持的标准,避免在赛场上时编译报错。
+需要指出的是,不同的 OJ 平台对 C++ 版本均不相同,例如 [最新的 ACM 比赛规则](https://icpc.baylor.edu/worldfinals/programming-environment) 支持 C++14 标准,而 [NOI 现行规则](http://www.noi.cn/newsview.html?id=559&hash=E4E249) 中指定的 g++ 4.8 [默认支持标准](https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Standards.html#Standards) 是 C++98。因此在学习 C++ 时要注意比赛支持的标准,避免在赛场上时编译报错。
## 标准模板库(STL)
## Boost 库
-[Boost](https://www.boost.org/) 是除了标准库外,另一个久副盛名的开源 C++ 工具库,其代码具有可移植、高质量、高性能、高可靠性等特点。Boost 中的模块数量非常之大,功能全面,并且拥有完备的跨平台支持,因此被看作 C++ 的准标准库。C++ 标准中的不少特性也都来自于 Boost,如智能指针、元编程、日期和时间等。尽管在 OI 中无法使用 Boost ,但是 Boost 中有不少轮子可以用来验证算法或者对拍,如 Boost.Geometry 有 R 树的实现, Boost.Graph 有图的相关算法, Boost.Intrusive 则提供了一套与 STL 容器用法相似的侵入式容器。有兴趣的读者可以自行在网络搜索教程。
+ [Boost](https://www.boost.org/) 是除了标准库外,另一个久副盛名的开源 C++ 工具库,其代码具有可移植、高质量、高性能、高可靠性等特点。Boost 中的模块数量非常之大,功能全面,并且拥有完备的跨平台支持,因此被看作 C++ 的准标准库。C++ 标准中的不少特性也都来自于 Boost,如智能指针、元编程、日期和时间等。尽管在 OI 中无法使用 Boost,但是 Boost 中有不少轮子可以用来验证算法或者对拍,如 Boost.Geometry 有 R 树的实现,Boost.Graph 有图的相关算法,Boost.Intrusive 则提供了一套与 STL 容器用法相似的侵入式容器。有兴趣的读者可以自行在网络搜索教程。
## 参考资料
-
-在 STL 中,迭代器( Iterator )是用来访问和检查 STL 容器中元素的对象,它的行为模式和指针类似,甚至有不少容器的迭代器类型就是指针。但是它封装了一些有效性检查,并且提供了统一的访问格式。迭代器尽管在使用上与常规的下标访问效果相似,但是由于部分 STL 容器(如 `std::list` )的下标访问有很大的开销,这时在顺序访问的情况下迭代器会比下标访问更加高效。类似的概念在其他很多高级语言中都存在,如 Python 的 `__iter__` 函数, C# 的 `IEnumerator`。
+在 STL 中,迭代器(Iterator)是用来访问和检查 STL 容器中元素的对象,它的行为模式和指针类似,甚至有不少容器的迭代器类型就是指针。但是它封装了一些有效性检查,并且提供了统一的访问格式。迭代器尽管在使用上与常规的下标访问效果相似,但是由于部分 STL 容器(如 `std::list` )的下标访问有很大的开销,这时在顺序访问的情况下迭代器会比下标访问更加高效。类似的概念在其他很多高级语言中都存在,如 Python 的 `__iter__` 函数,C# 的 `IEnumerator` 。
## 使用方法
-迭代器听起来比较晦涩,其实迭代器本身可以看作一个数据指针。迭代器主要有两个操作:自增和解引用( 单目 `*` [运算符](../op.md)),其中自增用来移动迭代器,解引用可以获取或修改它指向的元素。
+迭代器听起来比较晦涩,其实迭代器本身可以看作一个数据指针。迭代器主要有两个操作:自增和解引用(单目 `*` [运算符](../op.md) ),其中自增用来移动迭代器,解引用可以获取或修改它指向的元素。
最常用的使用方法是用迭代器替换普通的 `for` 循环,例如下列代码中两个循环的效果是一致的。(假设已经引用了 `std` 空间中的相关类型)
```cpp
vector<int> data(10);
-for(int i = 0; i < 10; i++)
- cout << data[i] << endl; // 使用下标访问元素
+for (int i = 0; i < 10; i++) cout << data[i] << endl; // 使用下标访问元素
-for(vector<int>::iterator iter = data.begin();
- iter != data.end(); iter++)
- cout << *iter << endl; // 使用迭代器访问元素
+for (vector<int>::iterator iter = data.begin(); iter != data.end(); iter++)
+ cout << *iter << endl; // 使用迭代器访问元素
// 在C++11后可以使用 auto iter = data.begin() 来简化上述代码
```
在 STL 的定义中,迭代器根据其支持的操作依次分为以下几类:
-- InputIterator:只要求支持拷贝、自增和解引访问
-- OutputIterator:只要求支持拷贝、自增和解引赋值
-- ForwardIterator:即同时满足 InputIterator 和 OutputIterator 的要求
-- Bidirectional:在 ForwardIterator 的基础上支持自减(即反向访问)
-- RandomAccess:在 Bidirectional 的基础上支持加减运算和比较运算(即随机访问)
+- InputIterator:只要求支持拷贝、自增和解引访问
+- OutputIterator:只要求支持拷贝、自增和解引赋值
+- ForwardIterator:即同时满足 InputIterator 和 OutputIterator 的要求
+- Bidirectional:在 ForwardIterator 的基础上支持自减(即反向访问)
+- RandomAccess:在 Bidirectional 的基础上支持加减运算和比较运算(即随机访问)
不同的 STL 容器支持的迭代器类型不同,在使用时需要留意。
## 算术运算符
-| 运算符 | 功能 |
-| ----- | --- |
-| `+` (单目) | 正 |
-| `-` (单目) | 负 |
+| 运算符 | 功能 |
+| --------- | --- |
+| `+` (单目) | 正 |
+| `-` (单目) | 负 |
| `*` (双目) | 乘法 |
-| `/` | 除法 |
-| `%` | 取模 |
+| `/` | 除法 |
+| `%` | 取模 |
| `+` (双目) | 加法 |
| `-` (双目) | 减法 |
-
-??? note “单目与双目运算符”
- 单目运算符(又称一元运算符)指被操作对象只有一个的运算符,而双目运算符(又称二元运算符)的被操作对象有两个。例如 `1+2` 中加号就是双目运算符,它有`1`和`2`两个被操作数。此外 C++ 中还有唯一的一个三目运算符`?:`。
+??? note“单目与双目运算符”
+ 单目运算符(又称一元运算符)指被操作对象只有一个的运算符,而双目运算符(又称二元运算符)的被操作对象有两个。例如 `1+2` 中加号就是双目运算符,它有 `1` 和 `2` 两个被操作数。此外 C++ 中还有唯一的一个三目运算符 `?:` 。
算术运算符中有两个单目运算符(正、负)以及五个双目运算符(乘法、除法、取模、加法、减法),其中单目运算符的优先级最高。
## 位运算符
-| 运算符 | 功能 |
-| ----- | --- |
-| `~` | 逐位非 |
-| `&` (双目) | 逐位与 |
-| `|` | 逐位或 |
-| `^` | 逐位异或 |
-| `<<` | 逐位左移 |
-| `>>` | 逐位右移 |
+| 运算符 | 功能 |
+| --------- | ---- |
+| `~` | 逐位非 |
+| `&` (双目) | 逐位与 |
+| `|` | 逐位或 |
+| `^` | 逐位异或 |
+| `<<` | 逐位左移 |
+| `>>` | 逐位右移 |
注意,位运算符的优先级低于普通的算数运算符。
## 成员访问运算符
-| 运算符 | 功能 |
-| ------ | ---- |
-| `[]` | 数组下标 |
-| `.` | 对象成员 |
+| 运算符 | 功能 |
+| --------- | -------- |
+| `[]` | 数组下标 |
+| `.` | 对象成员 |
| `&` (单目) | 取地址/获取引用 |
| `*` (单目) | 间接寻址/解引用 |
-| `->` | 指针成员 |
+| `->` | 指针成员 |
-这些运算符用来访问对象的成员或者内存,除了最后一个运算符外上述运算符都可被重载。与`&`, `*`和 `->` 相关的内容请阅读[指针](./pointer.md)和[引用](./reference.md)教程。这里还省略了两个很少用到的运算符`.*`和`->*`,其具体用法可以参见 [C++ 语言手册](https://zh.cppreference.com/w/cpp/language/operator_member_access)。
+这些运算符用来访问对象的成员或者内存,除了最后一个运算符外上述运算符都可被重载。与 `&` , `*` 和 `->` 相关的内容请阅读 [指针](./pointer.md) 和 [引用](./reference.md) 教程。这里还省略了两个很少用到的运算符 `.*` 和 `->*` ,其具体用法可以参见 [C++ 语言手册](https://zh.cppreference.com/w/cpp/language/operator_member_access) 。
```cpp
-auto result = v[1]; // 获取v中下标为2的对象
+auto result = v[1]; // 获取v中下标为2的对象
-auto result = p.q; // 获取p对象的q成员
+auto result = p.q; // 获取p对象的q成员
-auto result = p->q; // 获取p指针指向对象的q成员
+auto result = p -> q; // 获取p指针指向对象的q成员
-auto result = &v // 获取v的指针或引用
+auto result = &v // 获取v的指针或引用
-auto result = *v // 获取v指针指向的对象
+ auto result = *v // 获取v指针指向的对象
```