3

更新:我使用 MSVC10,它没有给我默认的移动语义

假设我想创建一个包含几个非 pod 成员的常规类;

class Foo {
NonPodTypeA a_;
NonPodTypeB b_;
}

像往常一样,我实现了一个复制构造函数和一个使用复制构造函数的赋值运算符:

Foo(const Foo& other) : a_(other.a_), b_(other.b_) {}
Foo& operator=(const Foo& other) { 
  Foo constructed(other);
  *this = std::move(constructed);
  return *this;
}

然后我实现 move-constructor 和 move-assignment,它对所有成员使用 std::swap 而不是 std::move,因为它们可能是在 move-semantics 可用之前编写的,因为实现了 move-semantics,我可以省略实现交换成员函数:

Foo(Foo&& other) {
  ::std::swap(a_, other._a);
  ::std::swap(b_, other._b);
}
Foo& operator=(Foo&& other) { 
  ::std::swap(a_, other._a);
  ::std::swap(b_, other._b);
  return *this;
}

这是我的问题;假设我对成员一无所知,这里可以做一些更笼统的事情吗?

例如,移动构造函数与 const 声明的成员不兼容,但是如果我实现移动构造函数,因为Foo(Foo&& other) : a_(std::move(other.a_)), b_(std::move(other.b_)){}我不能确定没有移动语义的类不会被复制?我可以以某种巧妙的方式在移动分配中使用移动构造函数吗?

4

2 回答 2

6

嗯,什么都不做。所有这些都是自动为您生成的1。唯一需要手动编写它们的时候是类处理资源时(然后您需要遵循三法则)。这也是以前的样子。现在唯一的区别是,您考虑了三法则之后,您可能出于语义(即制作仅移动对象)或性能(移动通常比复制更快)的原因想要实现移动成员。


1. MSVC 10 不会自动生成移动构造函数。在这种情况下,您可能想自己编写移动成员:(

于 2012-03-11T22:19:44.933 回答
1

鉴于 MSVC10 和 MSVC11 的局限性,您必须编写自己的移动构造函数/移动赋值运算符,以下是我所拥有的。我基于 Stephan T. Lavavej 的这段视频

http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n

class Foo 
{
public:

    //Note: don't pass param by reference. Unified assignment operator
    Foo& operator=(Foo other)
    {
        other.swap(*this);
        return *this;
    }

    Foo(Foo&& other)
      : a_(std::move(other.a_),
        b_(std::move(other.b_){}

    Foo(Foo& other)
      : a_(other.a_),
        b_(other.b_){}

private:
    void swap(Foo& other)
    {
        using std::swap;
        swap(a_, other.a_);
        swap(b_, other.b_);
    }

private:
    NonPodTypeA a_;
    NonPodTypeB b_;
};
于 2012-03-12T17:02:29.857 回答