矢量元素如何在矢量 std::move 之后保留其原始地址
How do vector elements preserve their original address after a vector std::move?
正如你在输出中看到的,向量的对象不仅pre
"移动"到向量post
,而且还在内存中保留了它们原来的地址空间。此举背后到底发生了什么?这种行为是意料之中的吗?假设我需要有一个指向这些对象的指针向量,是否可以安全地假设在此移动之后对象将始终具有其原始地址?
有一个类,其中包含这样的向量和我作为成员提到的指针向量。我还删除了复制 ctors,并为类定义了移动 ctors。
#include <iostream>
#include <vector>
struct B {
int val = 0;
B(int aInt) : val(aInt) { };
};
int main() {
std::vector<B> pre;
pre.push_back(B(1));
pre.push_back(B(2));
std::cout << "pre-move:t" << (void*)&pre.at(0) << 'n';
std::cout << "pre-move:t" << (void*)&pre.at(1) << 'n';
std::vector<B> post(std::move(pre));
std::cout << "post-move:t" << (void*)&post.at(0) << 'n';
std::cout << "post-move:t" << (void*)&post.at(1) << 'n';
return 0;
}
输出:
pre-move: 0x1d7b150
pre-move: 0x1d7b154 <------|
post-move: 0x1d7b150 |
post-move: 0x1d7b154 <------|
向量基本上只不过是指向堆分配内存、当前长度和当前容量的指针。
通过"移动"向量,您所做的只是复制这些值,并重置移出向量的值。
对于向量的数据,基本等价于
original_pointer = some_place_in_memory;
new_pointer = original_pointer; // Copies the *value* of original_pointer
original_pointer = nullptr;
无需分配新内存并复制矢量中的数据。
移动操作的全部意义在于避免复制元素,因此如果它们被复制(没有真正"移动"内存这样的事情),移动将只是一个副本。
向量通常实现为 3 个指针:开始、结束和容量。所有这些都指向动态分配的数组。然后移动向量只是复制这三个指针,因此数组和元素只是更改其所有者。
我认为应该安全地假设指向元素的指针仍然有效。
如果我们
编写语义上相等的代码而不std::vector
,那就很清楚了:
B* pre = new B[2]; // Declare std::vector<B> and allocate some space to make the following line correct
B[0] = 1; // pre.push_back(B(1));
B[1] = 2; // pre.push_back(B(2));
B* post = pre; // std::vector<B> post(std::move(pre));
实际上,向量移动归结为指针复制而不重新分配。指针指向的数据保留在其位置,因此矢量元素的地址不会更改。
在此代码示例中,第四行之后,pre
和 post
都指向具有相同地址的相同数据。
std::vector
是指向数组的指针的包装器,具有一些附加功能。所以在做完std::vector<B> post(std::move(pre));
之后,post
将包含一个与pre
中值相同的指针。
相关文章:
- 有根的二进制搜索树.保留与其父级的链接
- 为多个会话保留XPtr
- 将浮动的heightmap数组导出为16位原始值
- 给定一个向量,如何找到该向量的所有子集和的原始索引
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- 访问"std::vector"的保留但未调整大小的内存作为原始内存是否安全?
- 更改保留指向其字段的原始指针的对象地址
- STL 排序,保留原始顺序
- 如何在保留原始索引的同时对向量的向量进行排序
- 如何修复"文件保留原始位置,复制后不复制扩展名"?
- 如何在被调用后保留数组的原始值
- 如何在使用x进行计算时保留原始x的值
- 矢量元素如何在矢量 std::move 之后保留其原始地址
- 如何在不同的上下文(例如线程)中保留原始异常类型信息
- C++快速排序向量并保留原始索引号
- 在哪里可以找到保留标识符"__CLIBNS"的原始定义?
- 对容器进行排序,然后在保留原始排序的情况下移动元素
- 如果对赋给指针的迭代器进行自增操作,该指针是否保留原始内存位置?
- 保留指定的原始大小
- 在保留原始索引的同时对值进行更快的排序