mirror of
https://github.com/CnTransGroup/EffectiveModernCppChinese.git
synced 2025-02-06 17:20:44 +08:00
deploy: 0ecc9cd98f
This commit is contained in:
parent
78410558c2
commit
2bdba41ffc
@ -146,13 +146,13 @@
|
||||
<p>让我们从已知很多类型不支持移动操作开始这个过程。为了升级到C++11,C++98的很多标准库做了大修改,为很多类型提供了移动的能力,这些类型的移动实现比复制操作更快,并且对库的组件实现修改以利用移动操作。但是很有可能你工作中的代码没有完整地利用C++11。对于你的应用中(或者代码库中)的类型,没有适配C++11的部分,编译器即使支持移动语义也是无能为力的。的确,C++11倾向于为缺少移动操作的类生成它们,但是只有在没有声明复制操作,移动操作,或析构函数的类中才会生成移动操作(参考<a href="../3.MovingToModernCpp/item17.html">Item17</a>)。数据成员或者某类型的基类禁止移动操作(比如通过delete移动操作,参考<a href="../3.MovingToModernCpp/item11.html">Item11</a>),编译器不生成移动操作的支持。对于没有明确支持移动操作的类型,并且不符合编译器默认生成的条件的类,没有理由期望C++11会比C++98进行任何性能上的提升。</p>
|
||||
<p>即使显式支持了移动操作,结果可能也没有你希望的那么好。比如,所有C++11的标准库容器都支持了移动操作,但是认为移动所有容器的开销都非常小是个错误。对于某些容器来说,压根就不存在开销小的方式来移动它所包含的内容。对另一些容器来说,容器的开销真正小的移动操作会有些容器元素不能满足的注意条件。</p>
|
||||
<p>考虑一下<code>std::array</code>,这是C++11中的新容器。<code>std::array</code>本质上是具有STL接口的内置数组。这与其他标准容器将内容存储在堆内存不同。存储具体数据在堆内存的容器,本身只保存了指向堆内存中容器内容的指针(真正实现当然更复杂一些,但是基本逻辑就是这样)。这个指针的存在使得在常数时间移动整个容器成为可能,只需要从源容器拷贝保存指向容器内容的指针到目标容器,然后将源指针置为空指针就可以了:</p>
|
||||
<pre><code class="language-cpp">std::vector<Widget> vm1;
|
||||
<pre><code class="language-cpp">std::vector<Widget> vw1;
|
||||
|
||||
//把数据存进vw1
|
||||
…
|
||||
|
||||
//把vw1移动到vw2。以常数时间运行。只有vw1和vw2中的指针被改变
|
||||
auto vm2 = std::move(vm1);
|
||||
auto vw2 = std::move(vw1);
|
||||
</code></pre>
|
||||
<p><img src="media/item29_fig1.png" alt="item29_fig1" /></p>
|
||||
<p><code>std::array</code>没有这种指针实现,数据就保存在<code>std::array</code>对象中:</p>
|
||||
|
@ -4203,13 +4203,13 @@ public:
|
||||
<p>让我们从已知很多类型不支持移动操作开始这个过程。为了升级到C++11,C++98的很多标准库做了大修改,为很多类型提供了移动的能力,这些类型的移动实现比复制操作更快,并且对库的组件实现修改以利用移动操作。但是很有可能你工作中的代码没有完整地利用C++11。对于你的应用中(或者代码库中)的类型,没有适配C++11的部分,编译器即使支持移动语义也是无能为力的。的确,C++11倾向于为缺少移动操作的类生成它们,但是只有在没有声明复制操作,移动操作,或析构函数的类中才会生成移动操作(参考<a href="5.RRefMovSemPerfForw/../3.MovingToModernCpp/item17.html">Item17</a>)。数据成员或者某类型的基类禁止移动操作(比如通过delete移动操作,参考<a href="5.RRefMovSemPerfForw/../3.MovingToModernCpp/item11.html">Item11</a>),编译器不生成移动操作的支持。对于没有明确支持移动操作的类型,并且不符合编译器默认生成的条件的类,没有理由期望C++11会比C++98进行任何性能上的提升。</p>
|
||||
<p>即使显式支持了移动操作,结果可能也没有你希望的那么好。比如,所有C++11的标准库容器都支持了移动操作,但是认为移动所有容器的开销都非常小是个错误。对于某些容器来说,压根就不存在开销小的方式来移动它所包含的内容。对另一些容器来说,容器的开销真正小的移动操作会有些容器元素不能满足的注意条件。</p>
|
||||
<p>考虑一下<code>std::array</code>,这是C++11中的新容器。<code>std::array</code>本质上是具有STL接口的内置数组。这与其他标准容器将内容存储在堆内存不同。存储具体数据在堆内存的容器,本身只保存了指向堆内存中容器内容的指针(真正实现当然更复杂一些,但是基本逻辑就是这样)。这个指针的存在使得在常数时间移动整个容器成为可能,只需要从源容器拷贝保存指向容器内容的指针到目标容器,然后将源指针置为空指针就可以了:</p>
|
||||
<pre><code class="language-cpp">std::vector<Widget> vm1;
|
||||
<pre><code class="language-cpp">std::vector<Widget> vw1;
|
||||
|
||||
//把数据存进vw1
|
||||
…
|
||||
|
||||
//把vw1移动到vw2。以常数时间运行。只有vw1和vw2中的指针被改变
|
||||
auto vm2 = std::move(vm1);
|
||||
auto vw2 = std::move(vw1);
|
||||
</code></pre>
|
||||
<p><img src="5.RRefMovSemPerfForw/media/item29_fig1.png" alt="item29_fig1" /></p>
|
||||
<p><code>std::array</code>没有这种指针实现,数据就保存在<code>std::array</code>对象中:</p>
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user