应该何时编译生成移动构造函数?

时间:2012-11-01 10:18:25

标签: c++ visual-c++ c++11 visual-studio-2012 move-semantics

我使用VS11并使用以下内容:

class ContextWrapper
{
public:

    ContextWrapper()
    {
    } //it should be defaulted I *guess* in order to have automatic move constructor ?
      // no support in VS11 for that now  

    Context* GetContext()
    {
        return this->context.get();
    }

    void SetContext(std::unique_ptr<Context> context)
    {
        this->context = std::move(context);
    }

    //ContextWrapper(ContextWrapper&& other):  context(std::move(other.context))
    //{
    //} // I would like this to be generated by the compiler

private:
    ContextWrapper(const ContextWrapper&);
    ContextWrapper& operator= (const ContextWrapper&);

    std::unique_ptr<Context> context;
};

我希望这个类生成移动构造函数/赋值。事实是我没有一个琐碎的构造函数,因为我没有动作吗?还是有其他因素影响这个?

2 个答案:

答案 0 :(得分:21)

不幸的是,这部分C ++ 11不断变化。无论标准如何说,VC11还不可能实现它。所以今天,我不相信你能指望生成的移动成员。

然而,这是一个很好的问题,我希望得到一个很好的答案。

通常,如果您没有用户声明的复制成员或析构函数,编译器应生成移动成员。 = default= delete计为用户声明的。如果声明一个移动成员(例如移动构造函数),则不会隐式生成另一个移动成员。

不幸的是,C ++ 11继续说有时移动成员在用=default声明时被隐式删除,有时它们的生成取决于基础和成员是否具有移动成员或者是否可以轻易复制。这太复杂了,有时会出现令人惊讶的行为。以下是跟踪此错误的CWG问题:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1402

在我写这篇文章时,问题没有正确的提议解决方案。我希望在大约一周内改变。在俄勒冈州波特兰举行的2012年秋季C ++标准会议上,达成了一项基本上已达成协议的协议:

  1. 编译器永远不会隐式删除移动成员。
  2. 移动成员​​的隐式生成将始终与= default相同。
  3. 隐性生成不会取决于基础或成员的微不足道,也不会取决于移动时是否会抛出。
  4. 简而言之,我希望CWG 1402的纠正措辞简单地说:

      

    通常,如果没有,编译器应该生成移动成员   用户声明的复制成员也不是析构函数。 = default= delete   计为用户声明的。如果你声明一个移动成员(例如移动   构造函数),其他不会被隐式生成。   如果你=default成为移动成员,你会得到一些移动的东西   每个基地和成员。

    (适当的标准化)。我还没有看到会说这个的措辞。 Jason Merrill正在为我们写这篇文章。

    这意味着有时编译器会隐式生成抛出移动成员。但是我们采用的是简单的规则,但大多数情况下都做了正确的事情(很少有惊喜)。

答案 1 :(得分:4)

为了更直接地回答这个问题,Visual Studio不支持任何版本的隐式移动构造函数/赋值生成。因此,您必须始终手动将它们写出来。