为什么我不能使用auto声明变量?

时间:2016-01-18 15:34:23

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

当我尝试声明类的变量时,我在Visual Studio 2015中遇到编译错误,当这些类使用PIMPL模式时。

foo.h中:

#pragma once

class Foo
{
public:
  Foo(const std::wstring& str,
      const std::vector<std::wstring>& items);
  ~Foo();

private:
  struct Impl;
  std::unique_ptr<Impl> pimpl;
};

Foo.cpp中:

#include "stdafx.h"
#include "Foo.h"

struct Foo::Impl
{
public:
  Impl(const std::wstring& str,
       const std::vector<std::wstring>& items);

  std::wstring str_;
  std::vector<std::wstring> items_;
};

Foo::Foo(const std::wstring& str,
         const std::vector<std::wstring>& items)
  : pimpl(std::make_unique<Impl>(str, items))
{
}

Foo::~Foo() = default;

Foo::Impl::Impl(const std::wstring& str,
                const std::vector<std::wstring>& items)
  : str_(str),
  items_(items)
{
}

如果我使用传统语法声明类型Foo的变量,它编译得很好:

  Foo f(L"Hello", std::vector<std::wstring>());

但是,如果我使用auto声明它,那么我会收到编译错误:

  auto f2 = Foo { L"Goodbye", std::vector<std::wstring>() };
  

错误C2280:&#39; Foo :: Foo(const Foo&amp;)&#39;:尝试引用已删除的功能
  注意:编译器生成了&#39; Foo :: Foo&#39;这里

我了解应删除Foo的复制构造函数,因为unique_ptr无法复制。但是,我的理解是,当以这种方式声明变量时,结果将被移入变量或直接将值设置到变量中。

第二行在使用Visual Studio 2013时编译得很好。我检查了Visual Studio 2015中的重大更改,但我没有看到任何可以说明为什么会开始失败的内容。

我做错了什么,或者这种语法不能与不可复制的类型一起使用?

2 个答案:

答案 0 :(得分:10)

不会隐式声明move构造函数,因为你有一个用户声明的析构函数(参见[class.copy]/(9.4))。但是,复制构造函数被明确删除,因为unique_ptr无法复制。

您可以将移动构造函数显式声明为默认值。

答案 1 :(得分:5)

由于该类包含std::unique_ptr成员,因此编译器无法像通常那样生成复制构造函数,这意味着您的声明和初始化(调用复制构造函数)将无法实现。 / p>

您可以为您的班级设置move constructor并将其标记为default来解决此问题。