Aracılığıyla paylaş


Akıllı işaretçiler (Modern C++)

Modern C++ programlamada Standart Kitaplık, programların bellek ve kaynak sızıntılarından arındığından ve özel durum açısından güvenli olduğundan emin olmak için kullanılan akıllı işaretçiler içerir.

Akıllı işaretçiler için kullanım alanları

Akıllı işaretçiler, bellekstd<ad alanında tanımlanır. RAII veya Kaynak Alımı Başlatma programlama deyimi için çok önemlidir. Bu deyimin ana amacı, kaynak alımının nesnenin başlatılmasıyla aynı anda gerçekleşmesini sağlamaktır; böylece nesne için tüm kaynaklar bir kod satırında oluşturulur ve hazır hale getirilir. Pratikte temel RAII prensibi, yığın tarafından ayrılan herhangi bir kaynağın sahipliğini örneğin, dinamik olarak ayrılan belek veya sistem nesnesi tanıtıcıları, yok edicisi kaynağı silmek veya boşaltmak için gereken kodu ve herhangi bir temizleme kodunu içeren ve yığın tarafından ayrılan bir nesneye vermektir.

Çoğu durumda gerçek bir kaynağı işaret etmek ve işaretçiyi hemen bir akıllı işaretçiye dönüştürmek için bir ham işaretçi veya kaynak tanıtıcısı kullanırsınız. Modern C++ programlamada, ham işaretçiler yalnızca performansın önemli olduğu ve sahiplik konusunda karışıklık olma ihtimali bulunmayan kapsam, döngü veya yardımcı işlevler açısından sınırlı olan küçük kod engellerinde kullanılır.

Aşağıdaki örnek, bir ham işaretçi bildirimini bir akıllı işaretçi bildirimi ile karşılaştırır.

void UseRawPointer()
{
    // Using a raw pointer -- not recommended.
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars"); 

    // Use pSong...

    // Don't forget to delete!
    delete pSong;   
}

void UseSmartPointer()
{
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2...
    wstring s = song2->duration_;
    //...

} // song2 is deleted automatically here.

Akıllı işaretçi, örnekte gösterildiği gibi, yığında bildirdiğiniz ve yığın tarafından ayrılan nesneyi gösteren ham işaretçiyi kullanarak başlattığınız bir sınıf şablonudur. Akıllı işaretçi başlatıldıktan sonra ham işaretçiyi üstlenir. Bu, akıllı işaretçinin, ham işaretçinin belirttiği belleği silmekten sorumlu olduğu anlamına gelir. Akıllı işaretçi yok edici silinecek çağrıyı içerir ve akıllı işaretçi yığında bildirildiğinden, akıllı işaretçi kapsam dışına çıktığında, yığının daha ileri bir yerinde bir özel durum olsa bile, yok edicisi çağrılır.

Kapsüllenmiş işaretçiye, -> bilinen işaretçi işleçlerini ve *akıllı işaretçi sınıfının kapsüllenmiş ham işaretçiyi döndürmek için aşırı yüklendiği öğesini kullanarak erişin.

C++ akıllı işaretçi deyimi, C# gibi dillerde nesne oluşturmaya benzer: Nesneyi oluşturursunuz ve ardından sistemin doğru zamanda bunu silmesine izin verirsiniz. Fark arka planda ayrı bir çöp toplayıcının çalışmamasıdır; bellek standart C++ kapsama kuralları ile yönetilir, bu nedenle çalışma zamanı ortamı daha hızlı ve daha verimlidir.

Önemli

Akıllı işaretçileri, asla parametre listesinde değil, her zaman ayrı bir kod satırında oluşturun, böylece belli parametre listesi ayırma kuralları nedeniyle küçük kaynak sızıntıları meydana gelmesine engel olursunuz.

Aşağıdaki örnek, C++ Standart Kitaplığı'ndan akıllı unique_ptr işaretçi türünün büyük bir nesneye yönelik bir işaretçiyi kapsüllemek için nasıl kullanılabileceğini gösterir.

class LargeObject
{
public:
    void DoSomething(){}
};

void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{    
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method.
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope.

Örnek akıllı işaretçileri kullanmak için aşağıdaki temel adımları gösterir.

  1. Akıllı işaretçiyi otomatik bir (yerel) değişken olarak bildirin. (Akıllı işaretçinin new kendisinde veya malloc ifadesini kullanmayın.)

  2. Tür parametresinde kapsüllenen işaretçinin, işaret edilen türünü belirtin.

  3. Ham işaretçiyi newakıllı işaretçi oluşturucusunda -ed nesnesine geçirin. (Bazı yardımcı program işlevleri veya akıllı işaretçi oluşturucuları bunu sizin için yapar.)

  4. Nesnesine erişmek için aşırı yüklenmiş -> ve * işleçlerini kullanın.

  5. Akıllı işaretçinin nesneyi silmesine izin verin.

Akıllı işaretçiler bellek ve performans açısından mümkün olduğunda verimli olmak için tasarlanmıştır. Örneğin içindeki tek veri üyesi unique_ptr kapsüllenmiş işaretçidir. Bu, unique_ptr dört bayt veya sekiz bayt olan işaretçiyle tam olarak aynı boyutta olduğu anlamına gelir. * ve -> işleçleri aşırı yüklenmiş akıllı işaretçiyi kullanarak kapsüllenmiş işaretçiye erişmek ham işaretçilere doğrudan erişmekten önemli ölçüde daha yavaş değildir.

Akıllı işaretçiler, "nokta" gösterimi kullanılarak erişilen kendi üye işlevlerine sahiptir. Örneğin, bazı C++ Standart Kitaplığı akıllı işaretçileri, işaretçinin sahipliğini serbest bırakan bir sıfırlama üyesi işlevine sahiptir. Bu, aşağıdaki örnekte gösterildiği şekilde akıllı işaretçi kapsam dışında çıkmadan önce akıllı işaretçinin sahip olduğu belleği boşaltmak istediğinizde yararlıdır.

void SmartPointerDemo2()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Free the memory before we exit function block.
    pLarge.reset();

    // Do some other work...

}

Akıllı işaretçiler genelde ham işaretçilerine doğrudan erişmek için bir yol sağlar. C++ Standart Kitaplığı akıllı işaretçilerinin bu amaçla bir get üye işlevi vardır ve CComPtr ortak p sınıf üyesi vardır. Temel alınan işaretçiye doğrudan erişim sağladığınızda, akıllı işaretçiyi kendi kodunuzla bellek yönetmek amacıyla kullanırken, ham işaretçiyi de hala akıllı işaretçileri desteklemeyen koda geçirebilirsiniz.

void SmartPointerDemo4()
{
    // Create the object and pass it to a smart pointer
    std::unique_ptr<LargeObject> pLarge(new LargeObject());

    //Call a method on the object
    pLarge->DoSomething();

    // Pass raw pointer to a legacy API
    LegacyLargeObjectFunction(pLarge.get());    
}

Akıllı işaretçi türleri

Aşağıdaki bölümde Windows programlama ortamında bulunan farklı türden akıllı işaretçiler özetlenir ve bunların ne zaman kullanılacağı açıklanır.

C++ Standart Kitaplığı akıllı işaretçileri

Bu akıllı işaretçileri eski C++ nesnelerine (POCO) işaretçi kapsüllemek için ilk seçenek olarak kullanın.

  • unique_ptr
    Temel alınan işaretçi için, kesin olarak tek bir sahibe izin verir. poco için varsayılan seçenek olarak kullanın eğer bir ihtiyacınız shared_ptrolduğunu kesin olarak bilmiyorsanız. Bir yeni kullanıcıya taşınabilir, ancak kopyalanamaz veya paylaşılamaz. auto_ptrkullanım dışı olan öğesinin yerini alır. ile boost::scoped_ptrkarşılaştırın. unique_ptr küçük ve verimlidir; boyut bir işaretçidir ve C++ Standart Kitaplık koleksiyonlarından hızlı ekleme ve alma için rvalue başvurularını destekler. Üst bilgi dosyası: <memory>. Daha fazla bilgi için bkz . Nasıl yapılır: unique_ptr Örnekleri oluşturma ve kullanma ve unique_ptr Sınıfı.

  • shared_ptr
    Başvuru sayımı olan akıllı işaretçi. Birden fazla sahibe tek bir ham işaretçi atamak istediğinizde kullanın, örnek olarak bir kapsayıcıdan işaretçi kopyası döndürüp orijinalini saklamak istediğinizde kullanın. Ham işaretçi, tüm shared_ptr sahipler kapsamın dışına çıkana veya başka bir şekilde sahipliklerinden vazgeçene kadar silinmez. Boyut iki işaretçi kadardır; biri nesne için ve biri başvuru sayısını içeren paylaşılan denetim bloğu için. Üst bilgi dosyası: <memory>. Daha fazla bilgi için bkz. Nasıl yapılır: shared_ptr Örnekleri ve shared_ptr Sınıfı Oluşturma ve Kullanma.

  • weak_ptr
    ile shared_ptrbirlikte kullanmak için özel durumlu akıllı işaretçi. , weak_ptr bir veya daha fazla shared_ptr örneğe ait olan ancak başvuru sayımına katılmayan bir nesneye erişim sağlar. Bir nesneyi görmek istiyorsanız ancak canlı kalmasını istemiyorsanız kullanın. Bazı durumlarda örnekler arasındaki shared_ptr döngüsel başvuruları kesmek için gereklidir. Üst bilgi dosyası: <memory>. Daha fazla bilgi için bkz. Nasıl yapılır: weak_ptr Örnekleri ve weak_ptr Sınıfı Oluşturma ve Kullanma.

COM nesneleri için akıllı işaretçiler (klasik Windows programlama)

COM nesneleriyle çalışırken, arabirim işaretçilerini uygun akıllı işaretçi türüne sarın. Etkin Şablon Kitaplığı (ATL) çeşitli amaçlar için birçok akıllı işaretçi tanımlar. Derleyicinin _com_ptr_t .tlb dosyalarından sarmalayıcı sınıfları oluştururken kullandığı akıllı işaretçi türünü de kullanabilirsiniz. ATL üstbilgi dosyalarını eklemek istemediğinizde en iyi seçenektir.

CComPtr Sınıfı
ATL kullanabiliyorsanız bunu kullanın. ve AddRef yöntemlerini kullanarak Release başvuru sayımı gerçekleştirir. Daha fazla bilgi için bkz . Nasıl yapılır: CComPtr ve CComQIPtr Örnekleri Oluşturma ve Kullanma.

CComQIPtr Sınıfı
Benzerdir CComPtr ancak COM nesnelerinde çağırmak QueryInterface için basitleştirilmiş söz dizimi de sağlar. Daha fazla bilgi için bkz . Nasıl yapılır: CComPtr ve CComQIPtr Örnekleri Oluşturma ve Kullanma.

CComHeapPtr Sınıfı
Belleği boşaltmak için kullanılan CoTaskMemFree nesnelere akıllı işaretçi.

CComGITPtr Sınıfı
Genel arabirim tablosundan (GIT) alınan arabirimler için akıllı işaretçi.

_com_ptr_t Sınıfı
İşlevselliğe CComQIPtr benzer, ancak ATL üst bilgilerine bağımlı değildir.

POCO nesneleri için ATL akıllı işaretçileri

ATL, COM nesneleri için akıllı işaretçilere ek olarak, düz eski C++ nesneleri (POCO) için akıllı işaretçileri ve akıllı işaretçi koleksiyonlarını da tanımlar. Klasik Windows programlamada bu türler, özellikle kod taşınabilirliği gerekli olmadığında veya C++ Standart Kitaplığı ile ATL'nin programlama modellerini karıştırmak istemediğinizde C++ Standart Kitaplığı koleksiyonlarına yararlı alternatiflerdir.

CAutoPtr Sınıfı
Sahipliği bir kopyaya aktararak benzersiz sahipliği zorlayan akıllı işaretçi. Kullanım dışı bırakılan std::auto_ptr Sınıfla karşılaştırılabilir.

CHeapPtr Sınıfı
C malloc işlevi kullanılarak ayrılan nesneler için akıllı işaretçi.

CAutoVectorPtr Sınıfı
kullanılarak new[]ayrılan diziler için akıllı işaretçi.

CAutoPtrArray Sınıfı
Bir öğe dizisini CAutoPtr kapsülleyen sınıf.

CAutoPtrList Sınıfı
Düğüm listesini CAutoPtr işlemek için yöntemleri kapsülleyen sınıf.

Ayrıca bkz.

İşaretçiler
C++ Dil Başvurusu
C++ Standart Kitaplığı