当向量增长时,使用std :: move而不是copy来重新分配内存的好处?

时间:2015-01-06 01:32:24

标签: c++ move-semantics dynamic-memory-allocation

我正在阅读Lippman在C ++ Primer第5版中的StrVec(字符串向量)示例,在讨论重新分配的部分中,他们提到move会更有效率所有向量对象(strings)而不是复制。他写道:“我们StrVec的表现会更好 。”我理解这个推理,但我很好奇的是它实际上是如何影响内存中的对象的。

这个新分配的连续区域可能(保证?)在内存中的其他位置,所以向量对象所在的旧区域和新区域是不相连的,不是吗?

所以我们仍然需要对象移动到内存中的这个新区域,这不构成内存中的副本吗?我也明白它留下了这个旧区域的指针有效,但其中的值是垃圾。我猜这可能会有好处吗?如果是这样,怎么样?是因为未来的内存分配可以使用该区域吗?但是这将如何使矢量实现更快?

我会尝试向

说明我的问题

如果向量在内存中看起来像这样:

A:[|strings|]

我们为它分配新的空间

B:[----------------]

我们不需要复制字符串以便:

A:[xxxxxxxxx]
B:[|strings|-------]

我在这里缺少什么? 我承认移动语义对我来说并不明显,所以我认为我已经错过了这方面的明显好处。

更新

一定是累了,在本书的同一部分错过了这句话:

  

对于string,我们可以想象每个string都有一个指针   数组char。据推测,string移动构造函数复制了   指针而不是为字符分配空间和复制字符   自己。

3 个答案:

答案 0 :(得分:3)

字符数据不存储在实际的std::string对象本身中,而是存储在std::string指向的内存中的其他位置。所以你的std::vector看起来更像是这样:

       [data1a] [data2a] [data3a]
          ^        ^        ^
          |        |        |
VecA:[|string1a|string2a|string3a|...]

使用复制语义时,必须将字符数据复制到新内存中,例如:

       [xxxxxx] [xxxxxx] [xxxxxx]
          x        x        x
          x        x        x
VecB:[|string1b|string2b|string3b|string4b|...]
          |        |        |        |
          \/       \/       \/       \/
       [data1b] [data2b] [data3b] [data4b]

当使用移动语义时,新的std::string对象可以重用原始指针而不必复制现有数据:

       [data1a] [data2a] [data3a]
          ^        ^        ^
          |        |        |
VecB:[|string1b|string2b|string3b|string4b|...]
                                     |
                                     \/
                                  [data4b]

答案 1 :(得分:2)

实际的字符数据不在std::vector本身,而在堆中的其他位置。 std::string仅包含一些管家变量和指向字符数据的指针。因此,通过移动这些变量,重新分配的std::string中的新std::vector实例可以从原始std::string实例中窃取数据指针,而无需创建字符数据的新副本。

答案 2 :(得分:1)

因为字符串本身包含指向更多缓冲区中数据的指针!

A:[|||\] 
   ||\ [String3]
   |\ [String2]
   | [String1]
   [String0]

B:[....]  //uninitialized

如果复制A中的所有字符串,它们将依次复制其他四个缓冲区。但是,如果您字符串移动到B,那么他们只会转移现有缓冲区的所有权。