为什么不能将unique_ptr推回向量中?


217

该程序有什么问题?

#include <memory>
#include <vector>

int main()
{
    std::vector<std::unique_ptr<int>> vec;

    int x(1);
    std::unique_ptr<int> ptr2x(&x);
    vec.push_back(ptr2x); //This tiny command has a vicious error.

    return 0;
}

错误:

In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/mingw32/bits/c++allocator.h:34:0,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/allocator.h:48,
                 from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/memory:64,
                 from main.cpp:6:
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h: In member function 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = std::unique_ptr<int>, _Tp* = std::unique_ptr<int>*]':
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/stl_vector.h:745:6:   instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<int>, _Alloc = std::allocator<std::unique_ptr<int> >, value_type = std::unique_ptr<int>]'
main.cpp:16:21:   instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h:207:7: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_Deleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> = std::unique_ptr<int>]'
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/ext/new_allocator.h:105:9: error: used here
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/vector:69:0,
                 from main.cpp:7:
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h: In member function 'void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const std::unique_ptr<int>&}, _Tp = std::unique_ptr<int>, _Alloc = std::allocator<std::unique_ptr<int> >, std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::unique_ptr<int>*, std::vector<std::unique_ptr<int> > >, typename std::vector<_Tp, _Alloc>::_Base::_Tp_alloc_type::pointer = std::unique_ptr<int>*]':
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/stl_vector.h:749:4:   instantiated from 'void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<int>, _Alloc = std::allocator<std::unique_ptr<int> >, value_type = std::unique_ptr<int>]'
main.cpp:16:21:   instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/unique_ptr.h:207:7: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_Deleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> = std::unique_ptr<int>]'
c:\mingw\bin\../lib/gcc/mingw32/4.5.0/include/c++/bits/vector.tcc:314:4: error: used here

Answers:


328

您需要移动unique_ptr

vec.push_back(std::move(ptr2x));

unique_ptr确保单个unique_ptr容器拥有所持有指针的所有权。这意味着您不能复制的副本unique_ptr(因为两个unique_ptr拥有所有权),因此只能移动它。

但是请注意,您当前对的使用unique_ptr是不正确的。您不能使用它来管理指向局部变量的指针。局部变量的生存期是自动管理的:在块结束时(例如,在这种情况下,当函数返回时),局部变量将被销毁。您需要动态分配对象:

std::unique_ptr<int> ptr(new int(1));

12
由于只能存在一个,因此还应该能够将一个临时变量直接传递给向量:vec.push_back(std::unique_ptr<int>(new int(1)));unique_ptr也可以使用自定义删除器(不执行任何操作),但是必须考虑到局部变量的地址在作用域末尾变为无效。
UncleBens

18
另一个选择是使用emplace_back。例如vec.emplace_back(new int(1));
deft_code 2010年

75
@deft_code:不,那不安全。该emplace_back操作可能会抛出,如果这样做,则动态分配的int将被泄漏。经验法则是,所有动态分配都应由命名的智能指针拥有,以避免泄漏。
James McNellis'2

8
make_shared()返回shared_ptr,而不是unique_ptr。不幸的是,C ++ 11中没有make_unique()。不幸的遗漏,有望在C ++ 14中得到解决
cdmh

29
@FKaria make_unique()意味着new永远不需要直接调用它,从而改变了程序员的思维方式,避免了(显着减少了)内存泄漏。然后,在下一版的Meyers / Alexandrescu / Sutter的书中会出现“避免新建和删除”之类的建议:)
cdmh

24

std :: unique_ptr没有副本构造函数。您创建一个实例,然后要求std :: vector在初始化期间复制该实例。

error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::uniqu
e_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_D
eleter = std::default_delete<int>, std::unique_ptr<_Tp, _Tp_Deleter> =
 std::unique_ptr<int>]'

该类满足MoveConstructible和MoveAssignable的要求,但不满足CopyConstructible或CopyAssignable的要求。

以下适用于新的emplace调用。

std::vector< std::unique_ptr< int > > vec;
vec.emplace_back( new int( 1984 ) );

请参阅将unique_ptr与标准库容器一起使用以进一步阅读。


5
请参阅此注释 - emplace_x()使用智能指针时使用函数是不安全的。
Qix-蒙尼卡(Monica)失误'17

那么将unique_ptr存储到向量中的最佳方法是什么?与我测试过的原始指针相比,它非常慢。
user2189731
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.