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

Ghi*_*ita 14 c++ visual-c++ move-semantics c++11 visual-studio-2012

我使用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;
};
Run Code Online (Sandbox Code Playgroud)

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

How*_*ant 22

不幸的是,这部分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. 隐含的生成不会取决于基础或成员的微不足道,也不会取决于移动时是否会抛出.

简而言之,我希望CWG 1402的更正措辞简单地说:

通常,如果您没有用户声明的副本成员或析构函数,编译器应生成移动成员. = default= delete 计入用户声明.如果声明一个移动成员(例如移动构造函数),则不会隐式生成另一个移动成员.如果你=default是一个移动成员,你将获得移动每个基地和成员的东西.

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

这意味着有时编译器会隐式生成抛出移动成员.但是我们采用的是简单的规则,但大部分时间都是正确的(很少有惊喜).