Kullanmanın avantajı ( std::unique_ptr<T>
aramayı delete
veya delete[]
açıkça hatırlamak zorunda olmamanın yanı sıra ), bir işaretçinin nullptr
(temel) nesnenin geçerli bir örneğini işaret etmesini veya bir işaretçinin olduğunu garanti etmesidir. Soruna cevap sonra bu geri gelecektir, ancak ilk mesajdır DO dinamik olarak ayrılan nesnelerin ömrünü yönetmek için akıllı işaretçileri kullanır.
Şimdi, sorununuz aslında bunu eski kodunuzla nasıl kullanacağınızdır .
Benim önerim, mülkiyeti devretmek veya paylaşmak istemiyorsanız, her zaman nesneye referans vermelisiniz . İşlevinizi şu şekilde beyan edin ( const
gerektiği gibi niteleyicilerle veya niteleyiciler olmadan ):
bool func(BaseClass& ref, int other_arg) { ... }
Ardından, durumu std::shared_ptr<BaseClass> ptr
ele alan nullptr
ya da bool func(...)
sonucu hesaplamasını isteyen arayan kişi :
if (ptr) {
result = func(*ptr, some_int);
} else {
}
Bu, arayan herhangi bir kişinin referansın geçerli olduğuna ve işlev gövdesinin yürütülmesi boyunca geçerli olmaya devam edeceğine söz vermesi gerektiği anlamına gelir .
Burada şiddetle gerektiğine inanıyoruz nedeni budur değil akıllı işaretçiler ham işaretçileri veya referanslar geçmektedir.
Ham bir işaretçi yalnızca bir bellek adresidir. (En az) 4 anlamdan birine sahip olabilir:
- İstediğiniz nesnenin bulunduğu bir bellek bloğunun adresi. ( iyi )
- Emin olabileceğiniz 0x0 adresi referans alınamaz ve "hiçbir şey" veya "nesne yok" semantiğine sahip olabilir. ( kötü )
- İşleminizin adreslenebilir alanının dışında olan bir bellek bloğunun adresi (bunu referans almak, umarız programınızın çökmesine neden olur). ( çirkin )
- Başvurusu yapılabilen, ancak beklediğinizi içermeyen bir bellek bloğunun adresi. İşaretçi yanlışlıkla değiştirilmiş olabilir ve şimdi başka bir yazılabilir adresi (sürecinizdeki tamamen başka bir değişkenin) işaret ediyor. Bu bellek konumuna yazmak, zaman zaman yürütme sırasında çok eğlencenin olmasına neden olur, çünkü işletim sistemi, orada yazmaya izin verildiği sürece şikayet etmeyecektir. ( Zoinks! )
Akıllı işaretçileri doğru şekilde kullanmak, genellikle derleme sırasında tespit edilemeyen ve genellikle yalnızca programınız çöktüğünde veya beklenmedik şeyler yaptığında çalışma zamanında karşılaştığınız oldukça korkutucu durumları (3 ve 4) hafifletir.
Akıllı işaretçileri bağımsız değişken olarak const
aktarmanın iki dezavantajı vardır: Bir kopya yapmadan sivri uçlu nesnenin -ness değerini değiştiremezsiniz (bu, ek yük getirir shared_ptr
ve bunun için mümkün değildir unique_ptr
) ve yine de ikinci ( nullptr
) anlamıyla kalırsınız .
İkinci durumu tasarım açısından ( kötü ) olarak işaretledim . Bu, sorumluluk hakkında daha ince bir argüman.
Bir fonksiyonun nullptr
parametresi olarak a almasının ne anlama geldiğini bir düşünün . Önce onunla ne yapacağına karar vermesi gerekiyor: Kayıp nesnenin yerine "sihirli" bir değer mi kullanmalı? davranışı tamamen değiştirip başka bir şey hesaplayın (nesneyi gerektirmeyen)? paniklemek ve bir istisna atmak? Dahası, işlev ham gösterici ile 2 veya 3 veya daha fazla argüman aldığında ne olur? Her birini kontrol etmeli ve davranışını buna göre uyarlamalıdır. Bu, gerçek bir sebep olmaksızın girdi doğrulamanın üstüne yepyeni bir seviye ekler.
Arayan, bu kararları vermek için yeterli bağlamsal bilgiye sahip olmalıdır, ya da başka bir deyişle, ne kadar çok bilirseniz , kötü olan daha az korkutucudur. Öte yandan işlev, arayanın işaret ettiği hafızanın amaçlandığı gibi çalışmasının güvenli olduğuna dair sözünü almalıdır. (Referanslar hala bellek adresleridir, ancak kavramsal olarak bir geçerlilik vaadini temsil eder.)
std::unique_ptr
için camdan kurtuldunstd::vector<std::unique_ptr>
mu?