This commit is contained in:
y1yang0 2024-07-05 02:01:06 +00:00
parent 78410558c2
commit 2bdba41ffc
4 changed files with 6 additions and 6 deletions

View File

@ -146,13 +146,13 @@
<p>让我们从已知很多类型不支持移动操作开始这个过程。为了升级到C++11C++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&lt;Widget&gt; vm1;
<pre><code class="language-cpp">std::vector&lt;Widget&gt; 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>

View File

@ -4203,13 +4203,13 @@ public:
<p>让我们从已知很多类型不支持移动操作开始这个过程。为了升级到C++11C++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&lt;Widget&gt; vm1;
<pre><code class="language-cpp">std::vector&lt;Widget&gt; 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