Üye oluşturucu ve yıkıcı çağrılarının sırası


121

Oh C ++ guruları, bilgeliğini arıyorum. Bana standart olarak konuşun ve C ++ 'nın aşağıdaki programı garanti edip etmediğini söyleyin:

#include <iostream>
using namespace std;

struct A
{
    A() { cout << "A::A" << endl; }
    ~A() { cout << "A::~" << endl; }
};

struct B
{
    B() { cout << "B::B" << endl; }
    ~B() { cout << "B::~" << endl; }
};

struct C
{
    C() { cout << "C::C" << endl; }
    ~C() { cout << "C::~" << endl; }
};

struct Aggregate
{
    A a;
    B b;
    C c;
};

int main()
{
    Aggregate a;
    return 0;
}

her zaman üretecek

A::A
B::B
C::C
C::~
B::~
A::~

Başka bir deyişle, üyelerin beyan sırasına göre başlatılması ve ters sırada imha edilmesi garanti ediliyor mu?


8
Bu, sınıflar büyüdüğünde ve ağırlaştığında, ince böceklerin oldukça yaygın bir nedenidir. 50 veri üyeniz olduğunda ve bunların çoğu kurucu başlatıcı listesinde başlatıldığında, yapım sırasının başlatıcı listesindeki sıra olduğunu varsaymak kolay olabilir. Sonuçta, kod yazarları listeyi dikkatlice sıraladılar ... değil mi?
Permaquid

Yanıtlar:


140

Başka bir deyişle, üyelerin beyan sırasına göre başlatılması ve ters sırada imha edilmesi garanti ediliyor mu?

İkisine de evet. Bkz. 12.6.2

6 Başlatma aşağıdaki sırayla ilerleyecektir:

  • İlk olarak ve yalnızca aşağıda açıklanan en türetilmiş sınıfın kurucusu için, sanal temel sınıflar, temel sınıfların yönlendirilmiş döngüsel olmayan grafiğinin derinlikten önce soldan sağa geçişinde göründükleri sırayla başlatılacaktır. -to-right "türetilmiş sınıf temel-belirleyici-listesindeki temel sınıf adlarının görünme sırasıdır.

  • Daha sonra, doğrudan temel sınıflar, temel belirleyici listesinde göründükleri gibi (mem-başlatıcıların sırasına bakılmaksızın) bildirim sırasına göre başlatılacaktır.

  • Ardından, statik olmayan veri üyeleri, sınıf tanımında bildirildikleri sırayla başlatılır (yine mem-başlatıcıların sırasına bakılmaksızın).

  • Son olarak, yapıcı gövdesinin bileşik ifadesi çalıştırılır. [Not: Bildirim sırası, temel ve üye alt nesnelerinin başlatma sırasının tersine göre yok edilmesini sağlamak için zorunludur. - notu gönder]


2
Doğru hatırlıyorsam, ikisine de evet ... Bunu bir yığın olarak düşünün. İlk basıldı, son patladı. Böylece, ilk örneğinizi oluştururken, yığın sırasına göre belleğe aktarılır. Sonra ikincisi itilir, üçüncüsü ikincinin üzerine vb. Ardından, örneklerinizi yok ederken, program ilk yok edecek olanı, itilen sonuncuyu arayacaktır. Ama bu şekilde açıklamakta yanlış olabilirim, ancak C / C ++ ve ASM yaparken öğrendiğim yol bu.
Will Marcouiller

29

Evet, bunlar (statik olmayan üyeler). Başlatma (yapım) için 12.6.2 / 5 ve imha için 12.4 / 6'ya bakın.


10

Evet, standart, nesnelerin oluşturuldukları sıranın tersine doğru imha edilmesini garanti eder. Bunun nedeni, bir nesnenin diğerini kullanabilmesi, dolayısıyla ona bağlı olmasıdır. Düşünmek:

struct A { };

struct B {
 A &a;
 B(A& a) : a(a) { }
};

int main() {
    A a;
    B b(a);
}

Eğer adaha önce yıkılmak üzere olduğunu bsonra bgeçersiz üye başvurusu yapacağını. Nesneleri yaratıldıkları sıranın tersi sırayla imha ederek, doğru imhayı garanti ediyoruz.


Aslında bu kuralın kapsam üyelerinin imha sırasına da uygulanacağını hiç düşünmedim!
yano

6

Evet ve evet. Yok etme sırası, üye değişkenler için her zaman inşa sırasının tersidir.

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.