为什么我不能使用 auto 声明变量?
Why can't I declare a variable using auto?
我在 Visual Studio 2015 中尝试声明 class 的变量时出现编译错误,当时 classes 使用 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>() };
error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
note: compiler has generated 'Foo::Foo' here
我知道应该删除 Foo
的复制构造函数,因为 unique_ptr
无法复制。然而,我的理解是,当以这种方式声明变量时,结果要么被移动到变量中,要么直接将值设置到变量中。
第二行在使用 Visual Studio 2013 时编译正常。我检查了 Visual Studio 2015 中的重大更改,但我没有看到任何可以表明为什么开始失败的内容。
我是不是做错了什么,或者这个语法不能用于不可复制的类型?
因为 class 包含一个 std::unique_ptr
成员,编译器无法像通常那样生成 copy-constructor ,这意味着您的声明和初始化(调用 copy-constructor) 将不可能。
您可以通过为您的 class 制作一个 move constructor 并将其标记为 default
来解决它。
移动构造函数未隐式声明,因为您有一个 user-declared 析构函数(参见 [class.copy]/(9.4))。但是,显然删除了复制构造函数,因为无法复制unique_ptr
。
您可以将移动构造函数显式声明为默认构造函数。
我在 Visual Studio 2015 中尝试声明 class 的变量时出现编译错误,当时 classes 使用 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>() };
error C2280: 'Foo::Foo(const Foo &)': attempting to reference a deleted function
note: compiler has generated 'Foo::Foo' here
我知道应该删除 Foo
的复制构造函数,因为 unique_ptr
无法复制。然而,我的理解是,当以这种方式声明变量时,结果要么被移动到变量中,要么直接将值设置到变量中。
第二行在使用 Visual Studio 2013 时编译正常。我检查了 Visual Studio 2015 中的重大更改,但我没有看到任何可以表明为什么开始失败的内容。
我是不是做错了什么,或者这个语法不能用于不可复制的类型?
因为 class 包含一个 std::unique_ptr
成员,编译器无法像通常那样生成 copy-constructor ,这意味着您的声明和初始化(调用 copy-constructor) 将不可能。
您可以通过为您的 class 制作一个 move constructor 并将其标记为 default
来解决它。
移动构造函数未隐式声明,因为您有一个 user-declared 析构函数(参见 [class.copy]/(9.4))。但是,显然删除了复制构造函数,因为无法复制unique_ptr
。
您可以将移动构造函数显式声明为默认构造函数。