【问题标题】:Why can't I declare a variable using auto?为什么我不能使用 auto 声明变量?
【发布时间】:2016-04-23 20:15:39
【问题描述】:

当我尝试声明类的变量时,我在 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: 'Foo::Foo(const Foo &)': 试图引用已删除的函数
注意:编译器在这里生成了 'Foo::Foo'

我知道Foo 的复制构造函数应该被删除,因为unique_ptr 不能被复制。但是,我的理解是,当以这种方式声明变量时,结果要么被移动到变量中,要么直接将值设置到变量中。

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

我是不是做错了什么,或者这种语法不能用于不可复制的类型?

【问题讨论】:

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


    【解决方案1】:

    移动构造函数没有隐式声明,因为您有一个用户声明的析构函数(请参阅[class.copy]/(9.4))。但是,复制构造函数显然被删除了,因为unique_ptr不能被复制。

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

    【讨论】:

      【解决方案2】:

      由于类包含std::unique_ptr 成员,编译器无法像通常那样生成复制构造函数,这意味着您的声明和初始化(调用复制构造函数)将是不可能的。

      您可以通过为您的班级创建一个move constructor 并将其标记为default 来解决它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-09
        • 2014-11-09
        • 2020-09-04
        相关资源
        最近更新 更多