mirror of
https://github.com/CnTransGroup/EffectiveModernCppChinese.git
synced 2025-01-16 07:10:16 +08:00
fix item29; add item26-30
This commit is contained in:
parent
f74ebd2909
commit
b11895622a
@ -6,7 +6,7 @@
|
||||
|
||||
让我们从已知很多类型不支持移动操作开始这个过程。为了升级到C++11,C++98的很多标准库做了大修改,为很多类型提供了移动的能力,这些类型的移动实现比复制操作更快,并且对库的组件实现修改以利用移动操作。但是很有可能你工作中的代码没有完整地利用C++11。对于你的应用中(或者代码库中),没有适配C++11的部分,编译器即使支持移动语义也是无能为力的。的确,C++11倾向于为缺少移动操作定义的类默认生成,但是只有在没有声明复制操作,移动操作,或析构函数的类中才会生成移动操作(参考Item17)。禁止移动操作的类中(通过delete move operation 参考Item11),编译器不生成移动操作的支持。对于没有明确支持移动操作的类型,并且不符合编译器默认生成的条件的类,没有理由期望C++11会比C++98进行任何性能上的提升。
|
||||
|
||||
即使显式支持了移动操作,结果可能也没有你希望的那么好。比如,所有C++11的标准库都支持了移动操作,但是任务移动所有容器的开销都非常小是个错误。对于某些容器来说,压根就不存在开销小的方式来移动它所包含的内容。对另一些容器来说,开销真正小的移动操作却使得容器元素移动含义事与愿违。
|
||||
即使显式支持了移动操作,结果可能也没有你希望的那么好。比如,所有C++11的标准库都支持了移动操作,但是认为移动所有容器的开销都非常小是个错误。对于某些容器来说,压根就不存在开销小的方式来移动它所包含的内容。对另一些容器来说,开销真正小的移动操作却使得容器元素移动含义事与愿违。
|
||||
|
||||
考虑一下`std::array`,这是C++11中的新容器。`std::array`本质上是具有STL接口的内置数组。这与其他标准容器将内容存储在堆内存不同。存储具体数据在堆内存的容器,本身只保存了只想堆内存数据的指针(真正实现当然更复杂一些,但是基本逻辑就是这样)。这种实现使得在常数时间移动整个容器成为可能的,只需要拷贝容器中保存的指针到目标容器,然后将原容器的指针置为空指针就可以了。
|
||||
|
||||
@ -24,7 +24,7 @@ std::array<Widget, 10000> aw1;
|
||||
auto aw2 = std::move(aw1); // move aw1 into aw2. Runs in linear time. All elements in aw1 are moved into aw2.
|
||||
```
|
||||
|
||||
注意`aw1`中的元素被移动到了`aw2`中,这里假定`Widget`类的移动操作比复制操作快。但是使用`std::array`的移动操作还是复制操作都将话费线性时间的开销,因为每个容器中的元素终归需要拷贝一次,这与“移动一个容器就像操作几个指针一样方便”的含义想去甚远。
|
||||
注意`aw1`中的元素被移动到了`aw2`中,这里假定`Widget`类的移动操作比复制操作快。但是使用`std::array`的移动操作还是复制操作都将花费线性时间的开销,因为每个容器中的元素终归需要拷贝一次,这与“移动一个容器就像操作几个指针一样方便”的含义想去甚远。
|
||||
|
||||
另一方面,`std::strnig`提供了常数时间的移动操作和线性时间的复制操作。这听起来移动比复制快多了,但是可能不一定。许多字符串的实现采用了*small string optimization(SSO)*。"small"字符串(比如长度小于15个字符的)存储在了`std::string`的缓冲区中,并没有存储在堆内存,移动这种存储的字符串并不必复制操作更快。
|
||||
|
||||
|
@ -0,0 +1,2 @@
|
||||
## Item26: 避免在通用引用上重载
|
||||
|
@ -0,0 +1,2 @@
|
||||
## Item27:熟悉通用引用重载的替代方法
|
||||
|
@ -0,0 +1,2 @@
|
||||
## Item28:理解引用折叠
|
||||
|
@ -0,0 +1 @@
|
||||
## Item30:
|
Loading…
Reference in New Issue
Block a user