15

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

我希望这个类生成移动构造函数/赋值。我没有一个微不足道的构造函数的事实是我没有得到移动的原因吗?还是有其他因素影响这一点?

4

2 回答 2

23

不幸的是,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. move 成员的隐式生成将始终与= default.
  3. 隐式生成将不依赖于基础或成员的琐碎性,也不依赖于它们在移动时是否会抛出。

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

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

(适当标准化)。我还没有看到会这样说的措辞。Jason Merrill 正在为我们编写它。

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

于 2012-11-01T15:26:16.177 回答
4

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

于 2012-11-01T16:01:53.503 回答