移动构造函数和移动赋值运算符在不将指针作为成员变量保存并且不管理资源的类中有意义吗?

Coo*_*kes 1 c++

在我目前阅读的文章和书籍中,只有在持有指针的类中完成移动操作。这些操作从根本上通过交换指针并将旧指针设置为nullptr. 但是当std::move()使用默认赋值运算符在没有任何指针的情况下调用类时会发生什么?例子:

#include <iostream>

class MyClass
{
public:
    MyClass(int x) : x(x) {}
    int x = 0;
    MyClass& operator=(MyClass&& other) = default;
};

int main()
{
    MyClass a{ 10 };
    MyClass b{ 20 };

    std::cout << a.x << '\n';
    a = std::move(b);
    std::cout << a.x << '\n';
}
Run Code Online (Sandbox Code Playgroud)

结果是

10
20
Run Code Online (Sandbox Code Playgroud)

它似乎有效,但如何?它与普通的赋值运算符有什么不同吗?

Sam*_*hik 5

可以为任何类指定显式移动构造函数或移动运算符,无论它是否具有指针成员。确实,移动构造函数和运算符通常与具有某种指针的类一起使用。但这只是因为在这些情况下,有一种方法可以避免更昂贵的复制开销。

平凡类型的默认移动操作等效于复制操作。

类的默认移动操作相当于类的每个成员的移动操作。

因此,在您的示例中,移动操作等效于复制操作,并且没有可观察到的差异。

但是,无论出于何种原因,对于没有指针成员的类,当然可能需要移动运算符。一个经典的例子是std::thread,它有一个移动构造函数和一个赋值运算符,但没有等效的复制构造函数和复制赋值运算符。的内容std::thread是实现定义的,但通常由操作系统特定线程标识符的不透明句柄组成。这个句柄不能以任何有意义的方式“复制”,但它的所有权可以有意义地转移到另一个std::thread,这就是为什么你在那里有移动操作符。

您自己的类也可能有类似的语义要求,即使它们没有任何类型的指针。

  • 好吧,当您的秘密任务(如果您选择接受)是移动整个班级时,您可以按如下方式执行此任务:移动班级的第一个成员;然后移动班级的第二个成员;然后第三个,直到所有成员都被移动。然后,该类的每个成员根据自己的规则移动。 (2认同)