移动语义澄清
Move semantics clarification
我已经阅读了下面的帖子,它对移动语义提供了很好的见解:
有人可以向我解释移动语义吗?
但我仍然无法理解以下有关移动语义的事情 -
-
复制 elision 和 RVO 是否仍然适用于没有移动构造函数的类?
-
即使我们的类没有移动构造函数,但 STL 容器有一个。对于像这样的操作
std::vector vt = CreateMyClassVector();
并执行排序等操作。为什么 STL 不能在内部利用移动语义来使用不需要移动构造函数的复制 elision 或 RVO 等操作在内部改进此类操作?
3.在以下情况下,我们是否从移动语义中受益 -
std::vector
std::vector
由于整数是基元类型,因此移动整数元素不会提供任何优势。或者在这里移动操作 VT2 仅指向堆中的 VT1 内存,并且 VT1 设置为 null。到底发生了什么?如果是后者,那么即使是第 2 点也认为我们的类可能不需要 move 构造函数。
4. 当使用 std::move on lvalue 调用 push_back() 时,例如:
std::vector<MyClass> vt;
for(int i=0; i<10; ++i)
{
vt.push_back(MyClass());
}
MyClass obj;
vt.push_back(std::move(obj));
现在,由于 Vector 具有连续的内存分配,并且 OBJ 是在内存中的其他地方定义的,移动语义如何将 OBJ 内存移动到 Vector VT 连续内存区域,在这种情况下移动内存是否不如复制内存,移动如何通过简单地移动指向堆不同区域中的内存的指针来证明矢量连续内存要求。
提前感谢您的解释![按要求编辑了问题。
大多数语义不是移动记忆的方式。这一切都是关于对象的所有权从一个对象实例转移到另一个对象实例。执行此操作时:
std::string str1("Some string.");
std::string str2(std::move(str1));
std::string
分配和管理字符缓冲区。因此,每个std::string
都拥有一个内存缓冲区,其中包含字符串本身。
调用以构造str2
的移动构造函数将获取str1
分配的字符缓冲区,并将其从该对象中删除。因此,str2
现在有了str1
最初分配的指针,而str1
不再有该指针。这就是移动语义的全部内容:转移对象拥有的内存的所有权。
如果您的类没有 move 构造函数,std::vector
将不会调用它。明显地。因此,它无法利用移动构造函数可能带来的任何潜在优化。但是,这些优化机会仅适用于具有值语义且包含必须管理的资源的对象。否则,运动对你没有帮助。
一般规则是使用智能指针和容器对象,如vector
、string
等,以避免编写移动构造函数。因此,(如果您的编译器正确支持生成移动构造函数)资源管理会自动发生。
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 可以使用移动语义更改或改进此C++代码吗?
- c++在使用指针时移动语义
- 使用移动和复制语义时函数匹配如何工作?
- 移动语义和深层/浅层复制之间有什么关系?
- 了解构造函数在移动、复制、赋值语义中的行为
- std::unique_lock移动语义
- 移动语义和运算符 + 重载
- C++ 移动语义是否在任何情况下都能节省资源?
- 移动语义在这里如何工作?
- 使用移动语义:右值引用作为方法参数
- 在C++中使用移动语义的正确方法是什么?
- 移动语义 c++ 单链表
- C++:使用整数移动语义
- 当变量和参数名称匹配时,移动语义构造失败
- 在 C++11 中移动语义
- 方法冗余移动调用的移动语义
- 视觉理解移动C++标准的语义
- 如何通过move语义移动多个参数