Neden unique_ptr öğesini bir vektör içine itemiyorum?


217

Bu programda sorun nedir?

#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;
}

Hata:

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

Yanıtlar:


328

Aşağıdakileri taşımanız gerekir unique_ptr:

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

unique_ptrtek bir unique_ptrkabın tutulan işaretçiye sahip olduğunu garanti eder . Bu, a'nın kopyalarını yapamayacağınız anlamına gelir unique_ptr(çünkü o zaman iki unique_ptrs'nin mülkiyeti olurdu), böylece yalnızca taşıyabilirsiniz.

Ancak, geçerli kullanımınızın unique_ptryanlış olduğunu unutmayın . Yerel bir değişkenin işaretçisini yönetmek için kullanamazsınız. Yerel bir değişkenin ömrü otomatik olarak yönetilir: blok sona erdiğinde yerel değişkenler yok edilir (örneğin, bu durumda işlev döndüğünde). Nesneyi dinamik olarak ayırmanız gerekir:

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

12
Sadece bir tane olabileceği için, bir de vektör doğrudan geçici geçmek mümkün olmalıdır: vec.push_back(std::unique_ptr<int>(new int(1)));. unique_ptrözel bir silici de kullanabilir (hiçbir şey yapmaz), ancak o zaman yerel değişkenin adresinin kapsamın sonunda geçersiz hale geldiği dikkate alınmalıdır.
UncleBens

18
Başka bir seçenek kullanmaktır emplace_back. ör.vec.emplace_back(new int(1));
deft_code

75
@deft_code: Hayır, bu güvenli değil. emplace_backOperasyon atabilir ve bu olursa, dinamik tahsis intsızdırılmış edilecektir. Temel kural, sızıntıyı önlemek için tüm dinamik ayırmaların adlandırılmış bir akıllı işaretçiye sahip olması gerektiğidir.
James McNellis

8
make_shared () yöntemi bir unique_ptr değil paylaşılan bir_ptr döndürür. Ne yazık ki, C ++ 11'de make_unique () yoktur; Umarım C ++ 14'te düzeltilecek talihsiz bir ihmal
cdmh

29
@FKaria make_unique () newhiçbir zaman doğrudan çağrılmaya gerek olmadığı anlamına gelir , bu da programcının zihniyetini değiştirir ve bellek sızıntılarını önler (önemli ölçüde azaltır). "Yeni kaçının ve silin" gibi tavsiyeler Meyers / Alexandrescu / Sutter'ın kitabının bir sonraki baskısında görünebilir :)
cdmh

24

std :: unique_ptr hiçbir kopya oluşturucuya sahip değildir. Bir örnek oluşturun ve ardından std :: vector'dan başlatma sırasında bu örneği kopyalamasını isteyin .

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>]'

Sınıf, MoveConstructible ve MoveAssignable gereksinimlerini karşılar, ancak CopyConstructible veya CopyAssignable gereksinimlerini karşılamaz.

Aşağıdakiler yeni emplace çağrılarıyla çalışır .

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

Daha fazla bilgi için standard kütüphane kapları ile unique_ptr kullanma konusuna bakın .


5
Bu yoruma bakın - emplace_x()akıllı işaretçiler kullanılırken işlevlerin kullanımı güvenli değildir.
Qix - MONICA

Peki unique_ptr'i vektörde saklamanın en iyi yolu nedir? Test ettiğim gibi ham işaretçiye kıyasla son derece yavaş.
user2189731
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.