Merge pull request #750 from bennyyip/master

fix #749
This commit is contained in:
Milo Yip 2016-09-25 21:30:39 +08:00 committed by GitHub
commit ffc7942857
2 changed files with 12 additions and 12 deletions

View File

@ -163,9 +163,9 @@
## Document/Value (DOM)
1. 什么是转移语?为什么?
1. 什么是转移语?为什么?
`Value` 不用复制语意,而使用了转移语意。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
`Value` 不用复制语义,而使用了转移语义。这是指,当把来源值赋值于目标值时,来源值的所有权会转移至目标值。
由于转移快于复制,此设计决定强迫使用者注意到复制的消耗。

View File

@ -292,7 +292,7 @@ Value o(kObjectType);
Value a(kArrayType);
~~~~~~~~~~
## 转移语Move Semantics {#MoveSemantics}
## 转移语Move Semantics {#MoveSemantics}
在设计 RapidJSON 时有一个非常特别的决定,就是 Value 赋值并不是把来源 Value 复制至目的 Value而是把把来源 Value 转移move至目的 Value。例如
@ -302,13 +302,13 @@ Value b(456);
b = a; // a 变成 Nullb 变成数字 123。
~~~~~~~~~~
![使用移动语赋值。](diagram/move1.png)
![使用移动语赋值。](diagram/move1.png)
为什么?此语有何优点?
为什么?此语有何优点?
最简单的答案就是性能。对于固定大小的 JSON 类型Number、True、False、Null复制它们是简单快捷。然而对于可变大小的 JSON 类型String、Array、Object复制它们会产生大量开销而且这些开销常常不被察觉。尤其是当我们需要创建临时 Object把它复制至另一变量然后再析构它。
例如,若使用正常 * 复制 *
例如,若使用正常 * 复制 *
~~~~~~~~~~cpp
Value o(kObjectType);
@ -321,15 +321,15 @@ Value o(kObjectType);
}
~~~~~~~~~~
![复制语产生大量的复制操作。](diagram/move2.png)
![复制语产生大量的复制操作。](diagram/move2.png)
那个 `o` Object 需要分配一个和 contacts 相同大小的缓冲区,对 conacts 做深度复制,并最终要析构 contacts。这样会产生大量无必要的内存分配释放以及内存复制。
有一些方案可避免实质地复制这些数据例如引用计数reference counting、垃圾回收garbage collection, GC
为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 *。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
为了使 RapidJSON 简单及快速,我们选择了对赋值采用 * 转移 *。这方法与 `std::auto_ptr` 相似,都是在赋值时转移拥有权。转移快得多简单得多,只需要析构原来的 Value把来源 `memcpy()` 至目标,最后把来源设置为 Null 类型。
因此,使用转移语后,上面的例子变成:
因此,使用转移语后,上面的例子变成:
~~~~~~~~~~cpp
Value o(kObjectType);
@ -341,11 +341,11 @@ Value o(kObjectType);
}
~~~~~~~~~~
![转移语不需复制。](diagram/move3.png)
![转移语不需复制。](diagram/move3.png)
在 C++11 中这称为转移赋值操作move assignment operator。由于 RapidJSON 支持 C++03它在赋值操作采用转移语意,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语意
在 C++11 中这称为转移赋值操作move assignment operator。由于 RapidJSON 支持 C++03它在赋值操作采用转移语义,其它修改形函数如 `AddMember()`, `PushBack()` 也采用转移语义
### 转移语及临时值 {#TemporaryValues}
### 转移语及临时值 {#TemporaryValues}
有时候,我们想直接构造一个 Value 并传递给一个“转移”函数(如 `PushBack()``AddMember()`)。由于临时对象是不能转换为正常的 Value 引用,我们加入了一个方便的 `Move()` 函数: