unique_ptrをベクターにpush_backできないのはなぜですか?


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

回答:


328

を移動する必要がありますunique_ptr

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

unique_ptr単一のunique_ptrコンテナーが保持されたポインターの所有権を持つことを保証します。つまり、unique_ptr(2つunique_ptrのが所有権を持つため)のコピーを作成できないため、移動のみが可能です。

ただし、現在のの使用unique_ptrは正しくないことに注意してください。ローカル変数へのポインタの管理には使用できません。ローカル変数の有効期間は自動的に管理されます。ローカル変数は、ブロックが終了すると(たとえば、この場合は関数が戻ると)破棄されます。オブジェクトを動的に割り当てる必要があります:

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

12
存在できるのは1つだけなので、テンポラリを直接ベクトルに渡すこともできるはずですvec.push_back(std::unique_ptr<int>(new int(1)));unique_ptrカスタム削除機能(何もしない)を使用することもできますが、ローカル変数のアドレスがスコープの最後で無効になることを考慮する必要があります。
UncleBens 2010

18
別のオプションはを使用することemplace_backです。例vec.emplace_back(new int(1));
deft_code

75
@deft_code:いいえ、それは安全ではありません。emplace_back操作は投げることができる、そしてそれがない場合は、動的に割り当てられたintリークされます。経験則では、リークを回避するために、すべての動的割り当ては名前付きスマートポインタが所有する必要があります。
James McNellis、2012

8
make_shared()は、unique_ptrではなく、shared_ptrを返します。残念ながら、C ++ 11にはmake_unique()はありません。C ++ 14で修正されると思われる不幸な省略
cdmh 2013

29
@FKaria make_unique()はnew、直接呼び出す必要がないことを意味します。これにより、プログラマの考え方が変わり、メモリリークが回避されます(大幅に削減されます)。「新しいものを削除して削除する」などのアドバイスは、Meyers / Alexandrescu / Sutterの本の次の版に掲載されます:)
cdmh 2013年

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-モニカは2017

それで、unique_ptrをベクターに格納する最良の方法は何ですか?私がテストしたように、生のポインタと比較して非常に遅いです。
user2189731
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.