【问题标题】:So, how are basic classes written these days in C++11?那么,现在 C++11 中的基本类是如何编写的呢?
【发布时间】:2012-03-11 22:17:11
【问题描述】:

更新:我使用 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;
}

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

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

【问题讨论】:

  • 像往常一样,你什么也不做。让 a_ 和 b_ 照顾好自己。
  • 错误多于正确。除此之外,不要完全限定std::swap
  • ADL 应该用于调用swap,而不是显式限定(除非该限定是boost::swap,它将在内部使用ADL)。
  • ildjarn:我还是不明白,如果类中实现了 move-semantics,std::swap 会使用它(至少在 MSVC10 中)
  • @ViktorSehr:您不能向namespace std 添加重载。这就是您要从 ADL 命名空间中选择 swap 的原因。

标签: c++ c++11 class-design move-semantics rvalue


【解决方案1】:

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


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

【讨论】:

  • "MSVC 10 不会自动生成移动构造函数,但这是将在 MSVC 11 中添加的缺失功能。" 这不是我的理解。您有方便验证的链接吗?
  • VC11不会添加。更多地按照 VC 11.1 的思路思考。
  • @ildjarn 哎呀,我很困惑。看来它毕竟不在 VC11 中 :( blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
【解决方案2】:

鉴于 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_;
};

【讨论】:

    猜你喜欢
    • 2019-12-25
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    相关资源
    最近更新 更多