Yanıtlar:
Fonksiyonu süresi static
değişkenleri ilk kez başlar [0] program akış beyanı karşılaşır ve program sona sona erer. Bu, çalışma zamanının, yalnızca gerçekten inşa edilmişse, onu yok etmek için bir miktar kitap tutma gerçekleştirmesi gerektiği anlamına gelir.
Ek olarak, standart statik nesnelerin yıkıcılarının yapılarının tamamlanmasının tersi sırada çalışması gerektiğini söylediğinden [1] ve yapım sırası belirli program çalışmasına bağlı olabilir, yapım sırası dikkate alınmalıdır .
Misal
struct emitter {
string str;
emitter(const string& s) : str(s) { cout << "Created " << str << endl; }
~emitter() { cout << "Destroyed " << str << endl; }
};
void foo(bool skip_first)
{
if (!skip_first)
static emitter a("in if");
static emitter b("in foo");
}
int main(int argc, char*[])
{
foo(argc != 2);
if (argc == 3)
foo(false);
}
Çıktı:
C:> Örnek.exe
foo içinde düzenlendi
foo perişanımC:> Örnek.exe 1
eğer düzenlendi
foo içinde düzenlendi
foo perişanım
eğer perişanımC:> sample.exe 1 2
Oluşturuldu foo
oluşturulan Eğer yok
edildi Eğer
foo yok edildi
[0]
Yana C ++ 98 [2] Bu çok dişli bir ortamda davranır olacak kadar çok parçacığı için bir referans vardır belirtilmemiş, ve sorunlu olabilir Roddy bahseder.
[1]
C ++ 98 bölümü 3.6.3.1
[basic.start.term]
[2]
C ++ 11'de statik bir iş parçacığı güvenli bir şekilde başlatılır, bu Sihirli İstatistikler olarak da bilinir .
[basic.start.term]
Motti sipariş hakkında doğru, ancak dikkate alınması gereken başka şeyler var:
Derleyiciler genellikle yerel statiklerin zaten başlatılıp başlatılmadığını göstermek için gizli bir bayrak değişkeni kullanır ve bu bayrak işleve her girişte işaretlenir. Açıkçası bu küçük bir performans isabeti, ancak daha da endişe verici olan, bu bayrağın iş parçacığı için güvenli olduğu garanti edilmemesidir.
Yukarıdaki gibi bir yerel statikiniz varsa ve foo
birden çok iş parçacığından çağrılırsanız, plonk
yanlış veya hatta birden çok kez başlatılmasına neden olan yarış koşullarınız olabilir . Ayrıca, bu durumda plonk
, onu oluşturandan farklı bir iplikle tahrip olabilir.
Standardın söylediklerine rağmen, yerel statik yıkımın gerçek sırasına çok dikkat ederim, çünkü farkında olmadan hala yıkılmasından sonra hala geçerli olan bir statik varlığa güvenebilirsiniz ve bu izini bulmak gerçekten zordur.
Mevcut açıklamalar, 6.7'de bulunan Standardın gerçek kuralı olmadan tam olarak tamamlanmamıştır:
Statik depolama süresi veya iş parçacığı depolama süresi olan tüm blok kapsamı değişkenlerinin sıfır başlatılması, başka bir başlatma yapılmadan önce gerçekleştirilir. Varsa, statik depolama süresine sahip bir blok kapsamı varlığının sürekli başlatılması, bloğu ilk girilmeden önce gerçekleştirilir. Bir uygulamanın, ad alanı kapsamındaki statik veya iş parçacığı depolama süresine sahip bir değişkeni statik olarak başlatmasına izin verilen koşullar altında, statik veya iş parçacığı depolama süresine sahip diğer blok kapsamı değişkenlerinin erken başlatılmasına izin verilir. Aksi takdirde, böyle bir değişken kontrolün bildiriminden ilk kez geçtiğinde başlatılır; böyle bir değişken, başlatılmasının tamamlanmasının ardından başlatılmış sayılır. Başlatma bir istisna atarak çıkarsa, başlatma tamamlanmamıştır, bu nedenle kontrol bir sonraki deklarasyona girdiğinde tekrar denenecektir. Değişken başlatılırken kontrol bildirime eşzamanlı olarak girerse, eşzamanlı yürütme başlatmanın tamamlanmasını beklemelidir. Değişken başlatılırken denetim bildirime yinelemeli olarak tekrar girerse, davranış tanımsız olur.
FWIW, Codegear C ++ Builder standardına göre beklenen sırada yok olmaz.
C:\> sample.exe 1 2
Created in foo
Created in if
Destroyed in foo
Destroyed in if
... bu yıkım düzenine güvenmemenin bir başka nedeni!
Statik değişkenler kez devreye giriyor edilir programı yürütülmeye başlanmasından ve programın çalışması biter kadar kullanılabilir durumda kalır.
Statik değişkenler Belleğin Veri Segmentinde oluşturulur .