简体   繁体   English

具有显式析构函数和std :: unique_ptr <>成员的类不能在std :: vector <>中使用?

[英]Class with explicit destructor and std::unique_ptr<> member can't be used in std::vector<>?

This code 这段代码

#include <memory>
#include <vector>

class Foo
{
public:
    ~Foo()
    {
    }

    std::unique_ptr<int> bar;
};

int main()
{
    std::vector<Foo> foos;
    foos.emplace_back();
}

yields the following error message in g++: 在g ++中产生以下错误消息:

In file included from /usr/include/c++/4.8/memory:64:0,
                 from main.cpp:1:
/usr/include/c++/4.8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = Foo; _Args = {Foo}]’:
/usr/include/c++/4.8/bits/stl_uninitialized.h:75:53:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*; bool _TrivialValueTypes = false]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:117:41:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:258:63:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*; _Tp = Foo]’
/usr/include/c++/4.8/bits/stl_uninitialized.h:281:69:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Foo*; _ForwardIterator = Foo*; _Allocator = std::allocator<Foo>]’
/usr/include/c++/4.8/bits/vector.tcc:415:43:   required from ‘void std::vector<_Tp, _Alloc>::_M_emplace_back_aux(_Args&& ...) [with _Args = {}; _Tp = Foo; _Alloc = std::allocator<Foo>]’
/usr/include/c++/4.8/bits/vector.tcc:101:54:   required from ‘void std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {}; _Tp = Foo; _Alloc = std::allocator<Foo>]’
main.cpp:17:23:   required from here
/usr/include/c++/4.8/bits/stl_construct.h:75:7: error: use of deleted function ‘Foo::Foo(const Foo&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^
main.cpp:4:7: note: ‘Foo::Foo(const Foo&)’ is implicitly deleted because the default definition would be ill-formed:
 class Foo
       ^
main.cpp:4:7: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
In file included from /usr/include/c++/4.8/memory:81:0,
                 from main.cpp:1:
/usr/include/c++/4.8/bits/unique_ptr.h:273:7: error: declared here
       unique_ptr(const unique_ptr&) = delete;

yet if I remove the ~Foo() implementation (and declaration) it compiles just fine. 但是,如果我删除~Foo()实现(和声明),它编译就好了。 The same behaviour can be observed would main() look like this: 可以观察到相同的行为, main()看起来像这样:

int main()
{
    auto f = Foo();
}
  • Why is the copy constructor of Foo being called anyway? 为什么Foo调用Foo的拷贝构造函数? Shouldn't everything here happen via move semantics? 难道不应该通过移动语义来实现这里的一切吗?

  • Why wouldn't it (the copy constructor) be implicitly deleted if I remove the destructor? 如果我删除析构函数,为什么不隐式删除它(复制构造函数)?

The explicit destructor declaration (and definition) suppresses the implicit declaration of the move constructor and the move assignment operator. 显式析构函数声明(和定义)禁止移动构造函数和移动赋值运算符的隐式声明。 Thus the only thing that can be used is the copy constructor (which is implicitly declared no matter what) - but it's defined as deleted because unique_ptr s are not copyable. 因此,唯一可以使用的是复制构造函数(无论什么都隐式声明) - 但它被定义为已删除,因为unique_ptr是不可复制的。 Hence the error. 因此错误。

Explicitly default them - and the default constructor too since you have a user-declared constructor now: 显式默认它们 - 以及默认构造函数,因为你现在有一个用户声明的构造函数:

Foo() = default;
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;

Why wouldn't it (the copy constructor) be implicitly deleted if I remove the destructor? 如果我删除析构函数,为什么不隐式删除它(复制构造函数)?

It's still implicitly deleted. 它仍被隐式删除。 But since now a move constructor is implicitly declared, the move constructor can used for moving, and the copy constructor simply isn't used. 但是由于现在隐式声明了一个移动构造函数,移动构造函数可以用于移动,而复制构造函数根本就没有被使用。


Relevant standard quote (§12.8 [class.copy]/p9, 20, emphasis added): 相关标准引用(§12.8[class.copy] / p9,20,重点补充):

9 If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if 9如果类X的定义没有显式声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时

  • X does not have a user-declared copy constructor, X没有用户声明的复制构造函数,
  • X does not have a user-declared copy assignment operator, X没有用户声明的复制赋值运算符,
  • X does not have a user-declared move assignment operator, and X没有用户声明的移动赋值运算符,和
  • X does not have a user-declared destructor . X没有用户声明的析构函数

20 If the definition of a class X does not explicitly declare a move assignment operator, one will be implicitly declared as defaulted if and only if 20如果类X的定义没有显式地声明一个移动赋值运算符,那么当且仅当一个运算符默认时,它将被隐式声明为默认值

  • X does not have a user-declared copy constructor, X没有用户声明的复制构造函数,
  • X does not have a user-declared move constructor, X没有用户声明的移动构造函数,
  • X does not have a user-declared copy assignment operator, and X没有用户声明的复制赋值运算符,和
  • X does not have a user-declared destructor . X没有用户声明的析构函数

Foo is not copyable since it has a member unique_ptr . Foo不可复制,因为它有一个成员unique_ptr Foo is also not movable because declaration of a user-provided destructor suppresses the implicit generation of the default move constructor / assignment. Foo也不可移动,因为声明用户提供的析构函数会抑制默认移动构造函数/赋值的隐式生成。 If you want Foo to be movable default the move constructor/assignment so the compiler will generate them for you: 如果你希望Foo是可移动的默认移动构造函数/赋值,那么编译器将为你生成它们:

class Foo
{
public:
    ~Foo()
    {
    }

    Foo(Foo&&) = default;
    Foo& operator=(Foo&&) = default;

    std::unique_ptr<int> bar;
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我应该使用std :: unique_ptr <T> 在我班级的std :: vector成员变量中? - Should I use std::unique_ptr<T> in a std::vector member variable in my class? 分配std :: vector <std::unique_ptr<T> &gt;到另一个std :: vector <std::unique_ptr<T> &gt; - Assign std::vector<std::unique_ptr<T>> to another std::vector<std::unique_ptr<T>> std :: unique_ptr类成员上的ostream - ostream on a std::unique_ptr class member 可以将std :: unique_ptr用作参数吗? - Can std::unique_ptr be used as an argument? 构造类成员std :: vector的聪明方法 <std::unique_ptr<AClass> &gt; - Smart way to construct class member std::vector<std::unique_ptr<AClass> > 无法通过Diamond中的std :: unique_ptr访问最基类的受保护成员变量 - Can't access protected member variables of the most base class through std::unique_ptr in diamond 如何在构造函数初始值设定项列表中初始化std :: unique_ptr对象的类成员std :: vector? - How do I initialize a class member `std::vector` of `std::unique_ptr` object in the constructor initializer list? 移动std :: vector <std::unique_ptr<T> &gt;到std :: vector <std::shared_ptr<T> &gt; - Move std::vector<std::unique_ptr<T>> to std::vector<std::shared_ptr<T>> 返回对 std::vector 的引用范围<std::unique_ptr<t> &gt; </std::unique_ptr<t> - Returning a range of references to a std::vector<std::unique_ptr<T>> `std :: vector &lt;std :: unique_ptr &lt;T&gt;&gt;`出错 - Error with `std::vector< std::unique_ptr< T > >`
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM