Buradan benimsendi .
C ++ standart kitaplığındaki şablonların çoğu, tam türlerle başlatılmasını gerektirir. Ancak shared_ptr
ve unique_ptr
vardır kısmi istisnalar. Üyelerinin tamamı olmasa da bazıları eksik tiplerle somutlaştırılabilir. Bunun motivasyonu, akıllı işaretçiler kullanarak ve tanımlanmamış davranışları riske atmadan pimpl gibi deyimleri desteklemektir .
Tanımsız bir tipe sahip olduğunuzda ve bunu çağırdığınızda tanımlanmamış davranış oluşabilir delete
:
class A;
A* a = ...;
delete a;
Yukarıdaki yasal kod. Derlenecek. Derleyiciniz yukarıdaki gibi yukarıdaki kod için bir uyarı verebilir veya vermeyebilir. Yürütüldüğünde, muhtemelen kötü şeyler olacaktır. Çok şanslıysanız, programınız çökecektir. Ancak daha olası bir sonuç, programınızın sessiz bir şekilde bellek ~A()
çağrısında bulunmayacağıdır.
auto_ptr<A>
Yukarıdaki örnekte kullanmak yardımcı olmuyor. Ham bir işaretçi kullansanız bile tanımlanmamış davranışı elde edersiniz.
Bununla birlikte, bazı yerlerde eksik sınıfların kullanılması çok yararlıdır! Burası shared_ptr
ve unique_ptr
yardım. Bu akıllı işaretçilerin birinin kullanılması, tam bir türe sahip olmanın gerekli olduğu durumlar dışında, eksik bir türden kurtulmanıza izin verecektir. Ve en önemlisi, tam bir türe sahip olmak gerektiğinde, akıllı işaretçiyi o noktada eksik bir türle kullanmaya çalışırsanız derleme zamanı hatası alırsınız.
Artık tanımlanmamış davranış yok:
Kodunuz derlenirse, ihtiyacınız olan her yerde tam bir tür kullandınız.
class A
{
class impl;
std::unique_ptr<impl> ptr_; // ok!
public:
A();
~A();
// ...
};
shared_ptr
ve unique_ptr
farklı yerlerde tam bir tür gerektirir. Bunun nedenleri, dinamik bir deleter ile statik bir deleter arasındaki ilginin belirsiz olmasıdır. Kesin nedenler önemli değil. Aslında, çoğu kodda tam bir türün tam olarak nerede gerekli olduğunu bilmeniz gerçekten önemli değildir. Sadece kodlayın ve yanlış yaparsanız derleyici size söyleyecektir.
Bununla birlikte, size yardımcı olması durumunda, burada birkaç üyeyi shared_ptr
ve unique_ptr
eksiksizlik gerekliliklerini belgeleyen bir tablo bulunmaktadır . Üye tam bir tür gerektiriyorsa, girdide "C" bulunur, aksi takdirde tablo girdisi "I" ile doldurulur.
Complete type requirements for unique_ptr and shared_ptr
unique_ptr shared_ptr
+------------------------+---------------+---------------+
| P() | I | I |
| default constructor | | |
+------------------------+---------------+---------------+
| P(const P&) | N/A | I |
| copy constructor | | |
+------------------------+---------------+---------------+
| P(P&&) | I | I |
| move constructor | | |
+------------------------+---------------+---------------+
| ~P() | C | I |
| destructor | | |
+------------------------+---------------+---------------+
| P(A*) | I | C |
+------------------------+---------------+---------------+
| operator=(const P&) | N/A | I |
| copy assignment | | |
+------------------------+---------------+---------------+
| operator=(P&&) | C | I |
| move assignment | | |
+------------------------+---------------+---------------+
| reset() | C | I |
+------------------------+---------------+---------------+
| reset(A*) | C | C |
+------------------------+---------------+---------------+
İşaretçi dönüşümü gerektiren işlemler hem unique_ptr
ve için tam türler gerektirir shared_ptr
.
unique_ptr<A>{A*}
Yapıcı bir kurtulabiliriz eksik A
sadece derleyici bir çağrı kurmak için gerekli değilse ~unique_ptr<A>()
. Örneğin unique_ptr
, öbeğe koyarsanız, eksik bir şeyden kurtulabilirsiniz A
. Bu noktada fazla detay bulunabilir BarryTheHatchet en cevabı burada .
shared_ptr
/unique_ptr
" Sonundaki tablo sorunuzu cevaplamalıdır.