使用 std::move 重新分配内存的好处,而不是在矢量增长时复制
Benefits of reallocating memory with std::move instead of copy when vector grows?
我正在阅读Lippman的C++入门第5版中的StrVec
(字符串向量)示例,在讨论重新分配的部分中,他们提到move
所有向量对象(strings
)比复制更有效。他写道:"我们StrVec
的表现会好得多"。我理解这个推理,但我好奇的是这实际上如何影响内存中的对象。
这个新分配的连续区域可能(保证?)在内存中的其他地方,所以向量对象所在的旧区域和新区域是分离的,不是吗?
所以我们仍然需要将对象移动到内存中的这个新区域,这不构成内存中的副本吗?我也明白它使指向这个旧区域的指针有效,但其中的值是垃圾。我猜这可能是好处?如果是这样,如何?是因为将来的内存分配可以使用该区域吗?但是,这将如何使矢量实现更快?
我将尝试说明我的问题
如果矢量在内存中如下所示:
A:[|strings|]
我们为其分配新的空间
B:[----------------]
我们不需要复制字符串,以便:
A:[xxxxxxxxx]
B:[|strings|-------]
我在这里错过了什么?我承认移动语义对我来说并不明显,所以我认为我错过了这方面的明显好处。
更新
一定是累了,错过了书中同一节的这句话:
对于
string
,我们可以想象每个string
都有一个指向char
数组 .据推测,string
移动构造函数复制了 指针,而不是为字符分配空间和复制字符 他们自己。
字符数据不存储在实际的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]
实际的字符数据不在std::vector
本身中,而是在堆中的其他位置。std::string
仅包含一些内务变量和指向字符数据的指针。因此,通过移动这些变量,重新分配的std::vector
中的新std::string
实例可以从原始std::string
实例中窃取数据指针,而无需创建字符数据的新副本。
因为字符串本身包含指向更多缓冲区中的数据的指针!
A:[|||]
|| [String3]
| [String2]
| [String1]
[String0]
B:[....] //uninitialized
如果复制 A 中的所有字符串,它们将依次复制其他四个缓冲区。 但是,如果将字符串移动到 B
,则它们只会转移现有缓冲区的所有权。
- 新分配指向函数的指针是否合法?
- C++成功复制动态分配的 obj 而不复制 ctor?
- 在函数返回中返回对新分配的shared_ptr的尊重合法吗
- 如何删除新分配的字符,这也是函数返回值?
- C ++中新分配的int的内存大小,有没有不同更好的方法来查看它?
- 用于删除复制/移动分配运算符的有效签名
- 编译器忽略运算符新分配
- 覆盖复制/移动分配超载时,我是否需要删除当前的成员数据
- 方法向量的新/分配的复杂性::p ush_back
- 有没有一种方法可以全局填充新分配/删除分配
- 为什么我的新分配指针会自动在程序退出上删除
- 在 vector 的复制/移动分配下,底层存储会发生什么情况?
- 复制/移动操作符是否可以安全地用于实现复制/移动分配操作符
- 复制动态分配的 2D 数组
- 在班级中使用动态分配的C风格字符串,并带有复制和分配操作员,给出了意外的结果
- 在避免新分配的同时,const变量的复杂初始化
- 如何使具有包含唯一指针的成员变量的类可复制可分配
- 新分配的堆内存的初始内容 (VS2010)
- 带有复制/移动分配运算符的enable_if
- 使用Strcpy_s复制动态分配的字符数组