2

我已经阅读了下面的帖子,它很好地了解了移动语义:

有人可以向我解释一下移动语义吗?

但是我仍然无法理解有关移动语义的以下内容-

  1. 复制省略和 RVO 是否仍然适用于没有移动构造函数的类?

  2. 即使我们的类没有移动构造函数,但 STL 容器有一个。对于像这样的操作

std::vector vt = CreateMyClassVector();

并执行排序等操作。为什么 STL 不能在内部利用移动语义来使用不需要移动构造函数的复制省略或 RVO 等操作在内部改进此类操作?

3. 在以下情况下,我们是否受益于移动语义 -

std::vector<int> vt1(1000000, 5); // 创建并初始化 100 万个值为 5 的条目

std::vector<int> vt2(std::move(vt1)); // 移动 vt1 到 vt2

由于整数是原始类型,移动整数元素不会提供任何优势。或者在移动操作之后 vt2 只是指向堆中的 vt1 内存,并且 vt1 设置为 null。实际发生了什么?如果是后者,那么即使第 2 点也认为我们的类可能不需要移动构造函数。

4. 当使用 std::move 左值调用 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));

现在,由于向量具有连续的内存分配,并且 obj 在内存中的其他位置定义,移动语义如何将 obj 内存移动到向量 vt 连续内存区域,在这种情况下不移动内存与复制内存一样好,移动如何证明通过简单地移动指向堆的不同区域中的内存的指针来向量连续的内存需求。?

感谢您提前解释![按要求编辑问题。]

4

1 回答 1

3

大多数语义不是移动记忆的方式。这完全是关于将对象的所有权从一个对象实例转移到另一个对象实例。当你这样做时:

std::string str1("Some string.");
std::string str2(std::move(str1));

std::string分配和管理字符缓冲区。因此,每个人都std::string 拥有一个内存缓冲区,其中包含字符串本身。

调用来构造的移动构造函数str2将获取分配的字符缓冲区str1并将其从该对象中删除。因此str2现在有了str1最初分配的指针,并且str1不再有那个指针了。这就是移动语义的全部内容:转移对象拥有的内存的所有权。

如果您的类没有移动构造函数,std::vector则不会调用它。明显地。因此,它不能利用移动构造函数可能带来的任何潜在优化。但是这些优化机会存在于具有值语义并且包含必须管理的资源的对象。否则,运动对你没有帮助。

一般规则是使用智能指针和容器对象,如vectorstring等,以避免编写移动构造函数。因此,(如果您的编译器正确支持生成移动构造函数)资源管理会自动发生。

于 2013-01-30T12:29:22.507 回答