Saya cukup yakin bahwa variabel yang dideklarasikan secara global dialokasikan (dan diinisialisasi, jika berlaku) pada waktu mulai program.
int globalgarbage;
unsigned int anumber = 42;
Tapi bagaimana dengan yang statis yang didefinisikan dalam suatu fungsi?
void doSomething()
{
static bool globalish = true;
// ...
}
Kapan ruang untuk globalish
dialokasikan? Saya menebak kapan program dimulai. Tapi apakah itu juga diinisialisasi? Atau apakah itu diinisialisasi saat doSomething()
pertama kali dipanggil?
Beberapa verbiage relevan dari C ++ Standard:
sumber
If the initialization exits by throwing an exception, the initialization is not complete, so it will be tried again the next time control enters the declaration.
Memori untuk semua variabel statis dialokasikan pada pemuatan program. Tetapi variabel statis lokal dibuat dan diinisialisasi saat pertama kali digunakan, bukan saat program dijalankan. Ada beberapa bacaan bagus tentang itu, dan statika secara umum, di sini . Secara umum saya pikir beberapa masalah ini bergantung pada implementasinya, terutama jika Anda ingin tahu di mana di memori barang ini akan ditempatkan.
sumber
Kompilator akan mengalokasikan variabel statis yang ditentukan dalam suatu fungsi
foo
pada saat pemuatan program, namun kompilator juga akan menambahkan beberapa instruksi tambahan (kode mesin) ke fungsi Andafoo
sehingga saat pertama kali dipanggil, kode tambahan ini akan menginisialisasi variabel statis ( misalnya memanggil konstruktor, jika ada).@Adam: Ini di belakang layar injeksi kode oleh kompilator adalah alasan untuk hasil yang Anda lihat.
sumber
Saya mencoba menguji lagi kode dari Adam Pierce dan menambahkan dua kasus lagi: variabel statis di kelas dan tipe POD. Kompiler saya adalah g ++ 4.8.1, di OS Windows (MinGW-32). Hasilnya adalah variabel statis di kelas diperlakukan sama dengan variabel global. Konstruktornya akan dipanggil sebelum masuk ke fungsi utama.
Kesimpulan (untuk g ++, lingkungan Windows):
(1) : Status yang benar harus: "sebelum fungsi apa pun dari unit terjemahan yang sama dipanggil". Namun untuk sederhananya seperti contoh di bawah ini, maka itu adalah fungsi utama .
sertakan <iostream>
#include < string> using namespace std; class test { public: test(const char *name) : _name(name) { cout << _name << " created" << endl; } ~test() { cout << _name << " destroyed" << endl; } string _name; static test t; // static member }; test test::t("static in class"); test t("global variable"); void f() { static test t("static variable"); static int num = 10 ; // POD type, init before enter main function test t2("Local variable"); cout << "Function executed" << endl; } int main() { test t("local to main"); cout << "Program start" << endl; f(); cout << "Program end" << endl; return 0; }
hasil:
static in class created global variable created local to main created Program start static variable created Local variable created Function executed Local variable destroyed Program end local to main destroyed static variable destroyed global variable destroyed static in class destroyed
Ada yang diuji di Linux env?
sumber
Ya itu. Ini, antara lain, memungkinkan Anda menginisialisasi struktur data yang diakses secara global jika diperlukan, misalnya di dalam blok coba / tangkap. Misalnya, bukan
int foo = init(); // bad if init() throws something int main() { try { ... } catch(...){ ... } }
kamu bisa menulis
int& foo() { static int myfoo = init(); return myfoo; }
dan gunakan di dalam blok coba / tangkap. Pada panggilan pertama, variabel akan diinisialisasi. Kemudian, pada panggilan pertama dan berikutnya, nilainya akan dikembalikan (dengan referensi).
sumber
Variabel statis dialokasikan di dalam segmen kode - mereka adalah bagian dari gambar yang dapat dieksekusi, dan begitu juga dipetakan di yang sudah diinisialisasi.
Variabel statis dalam ruang lingkup fungsi diperlakukan sama, pelingkupannya murni konstruksi tingkat bahasa.
Untuk alasan ini Anda dijamin bahwa variabel statis akan diinisialisasi ke 0 (kecuali Anda menentukan sesuatu yang lain) daripada nilai yang tidak ditentukan.
Ada beberapa aspek lain untuk inisialisasi yang dapat Anda manfaatkan - misalnya, segmen bersama memungkinkan berbagai contoh yang dapat dieksekusi berjalan sekaligus untuk mengakses variabel statis yang sama.
Dalam C ++ (cakupan global), objek statis memiliki konstruktornya yang disebut sebagai bagian dari program yang dimulai, di bawah kendali pustaka runtime C. Di bawah Visual C ++ setidaknya urutan objek yang diinisialisasi dapat dikontrol oleh pragma init_seg .
sumber