SORU
19 HAZİRAN 2011, Pazar


C nesne imha

Tam olarak nesneleri C yok edilir , ve bu ne anlama geliyor? Çöp Toplayıcı yok beri elle yok etmek zorunda mıyım? Nasıl özel durumlar devreye girer?

(Not: Bu Stack Overflow's C FAQ için bir giriş olarak tasarlanmıştır. Eğer bu formda bir SSS sağlama fikri tenkit etmek istiyorsanız, o zaman the posting on meta that started all this bunu yapmak için bir yer olurdu. Cevaplar soru izlenen C chatroom nereye SSS fikir başladı ilk başta, bu da senin cevabın çok muhtemel alın okuyun o kim buldu bu fikri.)

CEVAP
19 HAZİRAN 2011, Pazar


Aşağıdaki metinde ayırt edeceğimkapsamlı nesnelerstatik olarak kapsayan kapsamı (fonksiyonlar, blok, sınıfları, ifadeler) tarafından belirlenen ve ., ^em>dinamik nesnelergenellikle çalışma zamanı kadar pek bilinmeyen.,

Sınıf nesneleri imha semantiği yıkıcılar tarafından belirlenirken, skaler bir nesne imha her zaman bir no-op. Özellikle, işaretçi değişken tahrip ediyordeğilbu pointee yok.

Kapsamlı nesneler

otomatik nesneler

Otomatik nesneleri (genellikle olarak anılacaktır "yerel değişkenler"), kontrol akış tanımının kapsamı ayrıldığında onların tanımı, ters sırayla yer yok

void some_function()
{
    Foo a;
    Foo b;
    if (some_condition)
    {
        Foo y;
        Foo z;
    }  <--- z and y are destructed here
}  <--- b and a are destructed here

Eğer bir istisna bir işlev yürütülürken atılırsa, daha önce inşa otomatik nesneler dışında arayan yayılır önce tahrip edilir. Bu süreç denirgevşemek yığını. Yığın çözülme sırasında, başka bir istisna daha önce inşa edilen söz konusu otomatik nesnelerin yıkıcı bırakabilir. Aksi takdirde, 8 ** işlev olarak adlandırılır.

Bu C en önemli faktörlerden biri neden olur

Yıkıcılar asla atmak gerekir.

yerel olmayan statik nesneler

Statik nesneler ad kapsamında tanımlanmış (yaygın olarak "genel değişkenler") ve statik veri üyeleri, kendi tanımı, main yürütülmesini sonra ters sırayla yer yok

struct X
{
    static Foo x;   // this is only a *declaration*, not a *definition*
};

Foo a;
Foo b;

int main()
{
}  <--- y, x, b and a are destructed here

Foo X::x;           // this is the respective definition
Foo y;

Statik nesneleri farklı çeviri birimleri olarak tanımlanan inşaat (ve yıkım) göreli sırasını tanımsız olduğunu unutmayın.

Eğer bir istisna statik bir nesnenin yıkıcı bırakırsa, std::terminate denilen bir işlemdir.

yerel statik nesneler

Statik nesneler fonksiyonlar (ve eğer) akış kontrolü ilk kez kendi tanımı geçerken inşa edilir içinde tanımlanmış.1 main yürütülmesini sonra: tersten tahrip ediyorlar

Foo& get_some_Foo()
{
    static Foo x;
    return x;
}

Bar& get_some_Bar()
{
    static Bar y;
    return y;
}

int main()
{
    get_some_Bar().do_something();    // note that get_some_Bar is called *first*
    get_some_Foo().do_something();
}  <--- x and y are destructed here   // hence y is destructed *last*

Eğer bir istisna statik bir nesnenin yıkıcı bırakırsa, 14 ** işlev olarak adlandırılır.

1: Bu son derece basitleştirilmiş bir modeldir. Statik nesneleri başlatma ayrıntılar aslında çok daha karmaşıktır.

temel sınıf subobjects ve üye subobjects

Kontrol akış bir nesne, üye subobjects yıkıcı vücuttan çıkınca (aynı zamanda olarak bilinen "veri üyeleri") tanımlarına ters sırada vuruldu. Bundan sonra, temel sınıf subobjects temel-belirleyici-liste ters sırada vuruldu

class Foo : Bar, Baz
{
    Quux x;
    Quux y;

public:

    ~Foo()
    {
    }  <--- y and x are destructed here,
};          followed by the Baz and Bar base class subobjects

Bir istisna sırasında atılırinşaatFoo'In subobjects, daha sonra önceden oluşturulmuş tüm subobjects dışında yayılır önce tahrip olacaktır. Foo yıkıcı, diğer taraftandeğilinfaz edilecek, Foo nesne asla tam olarak inşa edilmiştir beri.

Yıkıcı vücut veri üyeleri kendilerini tahrip sorumlu değildir unutmayın. Sadece ihtiyaç için yazmak bir yıkıcı bir veri üyesi için bir tanıtıcı bir kaynak ihtiyaçları için serbest zaman nesne yok (gibi bir dosya, bir yuva, bir veritabanı bağlantısı, bir dışlama veya yığın bellek).

dizi elemanları

Dizi elemanları büyükten küçüğe yok. Bir istisna sırasında atılırinşaatn-inci elemanı, 0 unsurları n-1 hariç yayılır önce tahrip edilir.

geçici nesneler

Geçici bir nesne sınıfı türü prvalue bir ifade değerlendirildiğinde inşa edilmiştir. Prvalue bir ifade en belirgin örneğidir değer bir nesneyi döndüren işlevi, T operator (const T&, const T&) gibi çağrı. Normal şartlar altında, geçici nesne lexically bu prvalue içeren tam ifade tamamen değerlendirildiğinde yok

__________________________ full-expression
              ___________  subexpression
              _______      subexpression
some_function(a   " "   b);
                          ^ both temporary objects are destructed here

Yukarıdaki işlev çağrısı some_function(a " " b) daha büyük bir ifadenin parçası değildir, çünkü tam ifade (bunun yerine, deyim-deyim bir parçası). Dolayısıyla, taşıyıcının değerlendirilmesi sırasında oluşturulmuş tüm nesneler geçici noktalı virgül de yok olacak. Böyle iki geçici nesneler vardır: ilk önce eklenmesi sırasında inşa edilmiştir, ve ikinci, ikinci ek sırasında inşa edilmiştir. İkinci geçici nesne ilk önce tahrip olacaktır.

Eğer bir istisna ikinci sırasında ayrıca atılırsa, önce geçici bir nesne düzgün hariç yayılıyor önce tahrip olacaktır.

Eğer yerel bir referans prvalue bir ifade ile başlatıldı, geçici nesnenin ömrü sarkan bir referans alamazsın yani yerel referans kapsamı genişletilmiştir

{
    const Foo& r = a   " "   b;
                              ^ first temporary (a   " ") is destructed here
    // ...
}  <--- second temporary (a   " "   b) is destructed not until here

Eğer sınıf olmayan tip prvalue bir ifade olarak değerlendirilir, sonuçdeğergeçici bir nesne değil. Ancak, geçici bir nesneeğer prvalue bir referans başlatmak için kullanılır oluşturulması:

const int& r = i   j;

Dinamik nesneleri ve diziler

Aşağıdaki bölümdeX yok"ilk X imha ve temel bellek serbest bırakın"demektir. Aynı şekildeX oluşturun"ilk yeterli bellek ayrılamadı ve X yapı var" demektir.

dinamik nesneler

Dinamik bir nesne p = new Foo ile oluşturulan delete p ile yok edilir. delete p, unutmayın eğer kaynak bir sızıntı var. Asla hepsi tanımsız davranışa neden beri aşağıdakilerden birini yapmak için çalışacağız.

  • delete[] ile dinamik bir nesne (not köşeli parantez), free veya başka bir anlamı yok
  • dinamik bir nesne birden çok kez yok
  • yok edildikten sonra dinamik bir nesne erişimi

Bir istisna sırasında atılırinşaatdinamik bir nesne, temel hafıza hariç yayılır önce serbest bırakılır. (Yıkıcı olacaktırdeğilnesne asla tam olarak inşa edildi çünkü bellek serbest bırakmak için önce yürütülür.)

dinamik bir dizi

Dinamik bir dizi p = new Foo[n] ile oluşturulan delete[] p (not köşeli parantez) yok. delete[] p, unutmayın eğer kaynak bir sızıntı var. Asla hepsi tanımsız davranışa neden beri aşağıdakilerden birini yapmak için çalışacağız.

  • delete, free veya başka yollarla dinamik bir dizi yok
  • dinamik bir dizi birden çok kez yok
  • yok edildikten sonra dinamik bir dizi erişim

Bir istisna sırasında atılırinşaatn-inci elemanı, elemanları n-1 0 azalan şekilde tahrip oldu, temel bellek serbest bırakılır ve bu durum yayılır.

(Genellikle dinamik bir dizi için Foo* std::vector<Foo> tercih etmelisiniz. Doğru ve sağlam kod yazmak çok daha kolay hale getirir.)

başvuru sayma akıllı işaretçiler

Dinamik bir nesne std::shared_ptr<Foo> çeşitli nesneler tarafından yönetilen std::shared_ptr<Foo> son nesne dinamik nesne paylaştığın dahil yıkımı sırasında yok edilir.

(Genel olarak Paylaşılan Nesneler için Foo* std::shared_ptr<Foo> tercih etmelisiniz. Doğru ve sağlam kod yazmak çok daha kolay hale getirir.)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Dogbert files

    Dogbert file

    12 Ocak 2012
  • Howard Pinsky

    Howard Pinsk

    6 AĞUSTOS 2006
  • Joshua Benedict

    Joshua Bened

    26 EKİM 2013