OSDN Git Service

style: format markdown files with remark-lint
author24OI-bot <15963390+24OI-bot@users.noreply.github.com>
Fri, 6 Sep 2019 01:29:56 +0000 (21:29 -0400)
committer24OI-bot <15963390+24OI-bot@users.noreply.github.com>
Fri, 6 Sep 2019 01:29:56 +0000 (21:29 -0400)
docs/lang/csl/iterator.md
docs/lang/op.md
docs/lang/reference.md

index 6ad416f..b9e04f0 100644 (file)
@@ -2,7 +2,7 @@
 
 ## 使用方法
 
-迭代器听起来比较晦涩,其实迭代器本身可以看作一个数据指针。迭代器主要有两个操作:自增和解引用([单目 `*` 运算符](../op.md)),其中自增用来移动迭代器,解引用可以获取或修改它指向的元素。
+迭代器听起来比较晦涩,其实迭代器本身可以看作一个数据指针。迭代器主要有两个操作:自增和解引用( [单目 `*` 运算符](../op.md) ),其中自增用来移动迭代器,解引用可以获取或修改它指向的元素。
 最常用的使用方法是用迭代器替换普通的 `for` 循环,例如下列代码中两个循环的效果是一致的。(假设已经引用了 `std` 空间中的相关类型)
 
 ```cpp
index fa84f9c..47f9e3f 100644 (file)
@@ -44,7 +44,7 @@ author: Ir1d, aofall
 
 有时我们需要让变量进行增加 1(自增)或者减少 1(自减),这时自增运算符 `++` 和自减运算符 `--` 就派上用场了。
 
-自增/自减运算符可放在变量前或变量后面,在变量前称为前缀,在变量后称为后缀,单独使用时前缀后缀无需特别区别,如果用于赋值语句时则需注意,具体可看下面的例子。详细情况可参考[引用](./reference.md)介绍的例子部分。
+自增/自减运算符可放在变量前或变量后面,在变量前称为前缀,在变量后称为后缀,单独使用时前缀后缀无需特别区别,如果用于赋值语句时则需注意,具体可看下面的例子。详细情况可参考 [引用](./reference.md) 介绍的例子部分。
 
 ```cpp
 i = 100;
index 6cd3dc2..712e919 100644 (file)
@@ -1,29 +1,29 @@
 引用可以看成是 C++ 封装的指针,用来传递它所指向的对象。在 C++ 代码中实际上会经常和引用打交道,但是通常不会显式地表现出来。引用的基本原则是在声明时必须指向对象,以及对引用的一切操作都相当于对原对象操作。另外,引用不是对象,因此不存在引用的数组、无法获取引用的指针,也不存在引用的引用。
 
-引用主要分为两种,左值引用和右值引用。此外还有两种特殊的引用:转发引用和垂悬引用,不作详细介绍。另外,本文还牵涉到一部分常值的内容,请用[常值](./const.md)一文辅助阅读。
+引用主要分为两种,左值引用和右值引用。此外还有两种特殊的引用:转发引用和垂悬引用,不作详细介绍。另外,本文还牵涉到一部分常值的内容,请用 [常值](./const.md) 一文辅助阅读。
 
 ## 左值引用
 
 ??? note "左值和右值"
-    在赋值表达式 `X = Y` 中,我们说 X 是左值,它被用到的是在内存中的**地址**,在编译时可知;而 Y 则是右值,它被用到的是它的**内容**(值),内容仅在运行时可知。在 C++11 之后值的概念被进一步分类,分为泛左值、纯右值和亡值,具体参见[相关文档](https://zh.cppreference.com/w/cpp/language/value_category)。值得一提的是,尽管右值引用在 C++11 后才支持,但是右值概念却更早就被定义了。
+    在赋值表达式 `X = Y` 中,我们说 X 是左值,它被用到的是在内存中的 **地址** ,在编译时可知;而 Y 则是右值,它被用到的是它的 **内容** (值),内容仅在运行时可知。在 C++11 之后值的概念被进一步分类,分为泛左值、纯右值和亡值,具体参见 [相关文档](https://zh.cppreference.com/w/cpp/language/value_category) 。值得一提的是,尽管右值引用在 C++11 后才支持,但是右值概念却更早就被定义了。
 
 ??? note "左值表达式"
     如果一个表达式返回的是左值(即可以被修改),那么这个表达式被称为左值表达式。右值表达式亦然。
 
-通常我们会接触到的引用为左值引用,它通常被用来被赋值和访问,指向右值,它的名称来源于它通常放在等号左边。左值需要**在内存中有实体**,而不能指向临时变量。以下是来自[参考手册](https://zh.cppreference.com/w/cpp/language/reference)的一段示例代码。
+通常我们会接触到的引用为左值引用,它通常被用来被赋值和访问,指向右值,它的名称来源于它通常放在等号左边。左值需要 **在内存中有实体** ,而不能指向临时变量。以下是来自 [参考手册](https://zh.cppreference.com/w/cpp/language/reference) 的一段示例代码。
 
 ```cpp
 #include <iostream>
 #include <string>
+
 int main() {
-    std::string s = "Ex";
-    std::string& r1 = s;
-    const std::string& r2 = s;
-    r1 += "ample";           // 修改 r1,即修改了 s
-//  r2 += "!";               // 错误:不能通过到 const 的引用修改
-    std::cout << r2 << '\n'; // 打印 r2,访问了s,输出 "Example"
+  std::string s = "Ex";
+  std::string& r1 = s;
+  const std::string& r2 = s;
+
+  r1 += "ample";  // 修改 r1,即修改了 s
+  //  r2 += "!";               // 错误:不能通过到 const 的引用修改
+  std::cout << r2 << '\n';  // 打印 r2,访问了s,输出 "Example"
 }
 ```
 
@@ -35,69 +35,67 @@ int main() {
 
 // 参数中的 s 是引用,在调用函数时不会发生拷贝
 char& char_number(std::string& s, std::size_t n) {
-    s += s; // 's' 与 main() 的 'str' 是同一对象
-            // 此处还说明左值也是可以放在等号右侧的
-    return s.at(n); // string::at() 返回 char 的引用
+  s += s;          // 's' 与 main() 的 'str' 是同一对象
+                   // 此处还说明左值也是可以放在等号右侧的
+  return s.at(n);  // string::at() 返回 char 的引用
 }
+
 int main() {
-    std::string str = "Test";
-    char_number(str, 1) = 'a'; // 函数返回是左值,可被赋值
-    std::cout << str << '\n'; // 此处输出 "TastTest"
+  std::string str = "Test";
+  char_number(str, 1) = 'a';  // 函数返回是左值,可被赋值
+  std::cout << str << '\n';   // 此处输出 "TastTest"
 }
 ```
 
 ## 右值引用 (C++ 11)
 
-右值引用是用来赋给其他变量的引用,指向右值,它的名称来源于它通常放在赋值号右边。右值**可以在内存里也可以在CPU寄存器中**。另外,右值引用可以被看作一种**延长临时对象生存期的方式**
+右值引用是用来赋给其他变量的引用,指向右值,它的名称来源于它通常放在赋值号右边。右值 **可以在内存里也可以在 CPU 寄存器中** 。另外,右值引用可以被看作一种 **延长临时对象生存期的方式** 
 
 ```cpp
 #include <iostream>
 #include <string>
-int main()
-{
-    std::string s1 = "Test";
-//  std::string&& r1 = s1;           // 错误:不能绑定到左值
-    const std::string& r2 = s1 + s1; // 可行:到常值的左值引用延长生存期
-//  r2 += "Test";                    // 错误:不能通过到常值的引用修改
-
-    std::string&& r3 = s1 + s1;      // 可行:右值引用延长生存期
-    r3 += "Test";                    // 可行:能通过到非常值的右值引用修改
-    std::cout << r3 << '\n';
+
+int main() {
+  std::string s1 = "Test";
+  //  std::string&& r1 = s1;           // 错误:不能绑定到左值
+
+  const std::string& r2 = s1 + s1;  // 可行:到常值的左值引用延长生存期
+  //  r2 += "Test";                    // 错误:不能通过到常值的引用修改
+
+  std::string&& r3 = s1 + s1;  // 可行:右值引用延长生存期
+  r3 += "Test";  // 可行:能通过到非常值的右值引用修改
+  std::cout << r3 << '\n';
 }
 ```
 
-在上述代码中, `r3` 是一个右值引用,引用的是右值 `s1 + s1`。`r2` 是一个左值引用,可以发现**右值引用可以转为 const 修饰的左值引用**
+在上述代码中, `r3` 是一个右值引用,引用的是右值 `s1 + s1` 。 `r2` 是一个左值引用,可以发现 **右值引用可以转为 const 修饰的左值引用** 
 
 ## 一些例子
 
-### `++i` 和 `i++`
+###  `++i` 和 `i++` 
 
-`++i` 和 `i++` 是典型的左值和右值。`++i` 的实现是直接给i变量加一,然后返回i本身。因为i是内存中的变量,因此可以是左值。实际上前自增的函数签名是`T& T::operator++();`。而 `i++`则不一样,它的实现是用临时变量存下i,然后再对 i 加一,返回的是临时变量,因此是右值。后自增的函数签名是`T T::operator++(int);`
+ `++i` 和 `i++` 是典型的左值和右值。 `++i` 的实现是直接给 i 变量加一,然后返回 i 本身。因为 i 是内存中的变量,因此可以是左值。实际上前自增的函数签名是 `T& T::operator++();` 。而 `i++` 则不一样,它的实现是用临时变量存下 i,然后再对 i 加一,返回的是临时变量,因此是右值。后自增的函数签名是 `T T::operator++(int);` 
 
 ```cpp
 int n1 = 1;
 int n2 = ++n1;
-int n3 = ++ ++n1; // 因为是左值,所以可以继续操作
+int n3 = ++++n1;  // 因为是左值,所以可以继续操作
 int n4 = n1++;
 //  int n5 = n1++ ++;   // 错误,无法操作右值
 //  int n6 = n1 + ++n1; // 未定义行为
-int&& n7 = n1++; // 利用右值引用延长生命期
-int n8 = n7++; // n8 = 1
+int&& n7 = n1++;  // 利用右值引用延长生命期
+int n8 = n7++;    // n8 = 1
 ```
 
-### 移动语义和 `std::move` ( C++11 )
+### 移动语义和 `std::move` (C++11)
 
-在 C++11 之后,C++ 利用右值引用新增了移动语义的支持,用来避免对象在堆空间的复制( 但是无法避免栈空间复制 ), STL 容器对该特性有完整支持。具体特性有[移动构造函数](https://zh.cppreference.com/w/cpp/language/move_constructor)、[移动赋值](https://zh.cppreference.com/w/cpp/language/move_assignment)和具有移动能力的函数(参数里含有右值引用)。
-另外,`std::move` 函数可以用来产生右值引用,需要引用 `<utility>` 头文件。
+在 C++11 之后,C++ 利用右值引用新增了移动语义的支持,用来避免对象在堆空间的复制(但是无法避免栈空间复制),STL 容器对该特性有完整支持。具体特性有 [移动构造函数](https://zh.cppreference.com/w/cpp/language/move_constructor) 、 [移动赋值](https://zh.cppreference.com/w/cpp/language/move_assignment) 和具有移动能力的函数(参数里含有右值引用)。
+另外, `std::move` 函数可以用来产生右值引用,需要引用 `<utility>` 头文件。
 
 ```cpp
-
 // 移动构造函数
-std::vector<int> v{1,2,3,4,5};
-std::vector<int> v2(std::move(v)); // 移动v到v2, 不发生拷贝
+std::vector<int> v{1, 2, 3, 4, 5};
+std::vector<int> v2(std::move(v));  // 移动v到v2, 不发生拷贝
 assert(v.empty());
 
 // 移动赋值函数
@@ -109,7 +107,6 @@ assert(v2.empty());
 std::string s = "def";
 std::vector<std::string> numbers;
 numbers.push_back(std::move(s));
-
 ```
 
 注意上述代码仅在 C++11 之后可用。
@@ -119,24 +116,19 @@ numbers.push_back(std::move(s));
 让函数返回引用值可以避免函数在返回时对返回值进行拷贝,如
 
 ```cpp
-char &get_val(std::string &str, int index)
-{
-    return str[index];
-}
+char &get_val(std::string &str, int index) { return str[index]; }
 ```
 
 尽管有了右值引用,你仍然不能返回在函数中新分配的栈空间,如果一定要在函数内分配新的空间并返回,请使用堆分配。例如如下两个函数都会导致内存错误。
 
 ```cpp
-std::vector<int> & getLVector ()
-{
-    std::vector<int> x{1};
-    return x;
+std::vector<int>& getLVector() {
+  std::vector<int> x{1};
+  return x;
 }
-std::vector<int> && getRVector ()
-{
-    std::vector<int> x{1};
-    return std::move(x);
+std::vector<int>&& getRVector() {
+  std::vector<int> x{1};
+  return std::move(x);
 }
 ```
 
@@ -146,15 +138,14 @@ std::vector<int> && getRVector ()
 struct Beta {
   Beta_ab ab;
   Beta_ab const& getAB() const& { return ab; }
-  Beta_ab && getAB() && { return move(ab); }
+  Beta_ab&& getAB() && { return move(ab); }
 };
 
-Beta_ab ab = Beta().getAB(); // 这里是移动语义,而非拷贝
+Beta_ab ab = Beta().getAB();  // 这里是移动语义,而非拷贝
 ```
 
 ## 参考内容
 
-1. [C++ 语言文档 —— 引用声明](https://zh.cppreference.com/w/cpp/language/reference)
-2. [C++ 语言文档 —— 值类别](https://zh.cppreference.com/w/cpp/language/value_category)
-3. [Is returning by rvalue reference more efficient?](https://stackoverflow.com/questions/1116641/is-returning-by-rvalue-reference-more-efficient)
-
+1.   [C++ 语言文档——引用声明](https://zh.cppreference.com/w/cpp/language/reference) 
+2.   [C++ 语言文档——值类别](https://zh.cppreference.com/w/cpp/language/value_category) 
+3.   [Is returning by rvalue reference more efficient?](https://stackoverflow.com/questions/1116641/is-returning-by-rvalue-reference-more-efficient)