Variabel statis dalam fungsi anggota


158

Dapatkah seseorang tolong jelaskan bagaimana variabel statis dalam fungsi anggota bekerja di C ++.

Diberi kelas berikut:

class A {
   void foo() {
      static int i;
      i++;
   }
}

Jika saya mendeklarasikan beberapa instance A, apakah memanggil foo()satu instance menambahkan variabel statis ipada semua instance? Atau hanya yang dipanggil?

Saya berasumsi bahwa setiap instance akan memiliki salinannya sendiri i, tetapi melangkah melalui beberapa kode yang sepertinya menunjukkan sebaliknya.

Jawaban:


169

Karena class Aadalah kelas non-template dan A::foo()merupakan fungsi non-template. Hanya akan ada satu salinan static int idi dalam program.

Setiap instance Aobjek akan mempengaruhi hal yang sama idan masa hidup iakan tetap ada selama program. Untuk menambahkan contoh:

A o1, o2, o3;
o1.foo(); // i = 1
o2.foo(); // i = 2
o3.foo(); // i = 3
o1.foo(); // i = 4

3
Terima kasih atas contoh yang bagus! Apakah akan ada cara untuk benar-benar mencapai sesuatu yang membuat ruang lingkup static int ispesifik untuk contoh, sehingga misalnya o1.foo(); // i = 1dan $o2.foo(); // i = 1...?
Stingery

14
Meskipun ini mungkin bukan gaya yang Anda cari, membuat data pribadi anggota kelas A akan memiliki efek yang Anda gambarkan. Jika Anda khawatir tentang konflik nama, Anda bisa menambahkan awalan seperti m_untuk menunjukkan status i.
Carl Morris

137

staticSayangnya, kata kunci memiliki beberapa arti yang tidak terkait dalam C ++

  1. Ketika digunakan untuk anggota data itu berarti bahwa data dialokasikan di kelas dan bukan dalam hal.

  2. Ketika digunakan untuk data di dalam suatu fungsi, itu berarti bahwa data dialokasikan secara statis, diinisialisasi saat pertama kali blok dimasukkan dan berlangsung hingga program berhenti. Juga variabel hanya terlihat di dalam fungsi. Fitur khusus statika lokal ini sering digunakan untuk menerapkan konstruksi malas lajang.

  3. Ketika digunakan pada level unit kompilasi (modul) itu berarti bahwa variabel itu seperti global (yaitu dialokasikan dan diinisialisasi sebelum maindijalankan dan dihancurkan setelah mainkeluar) tetapi variabel tidak akan dapat diakses atau terlihat di unit kompilasi lainnya .

Saya menambahkan beberapa penekanan pada bagian yang paling penting untuk setiap penggunaan. Penggunaan (3) agak tidak disukai demi ruang nama yang tidak disebutkan namanya yang juga memungkinkan deklarasi kelas yang tidak diekspor.

Dalam kode Anda, statickata kunci digunakan dengan arti nomor 2 dan tidak ada hubungannya dengan kelas atau instance ... itu adalah variabel dari fungsi dan hanya akan ada satu salinannya.

Seperti yang benar iammilind katakan namun bisa saja ada beberapa contoh dari variabel itu jika fungsi itu adalah fungsi templat (karena dalam kasus itu memang fungsi itu sendiri dapat hadir dalam banyak salinan berbeda dalam program). Bahkan dalam kasus kelas kursus dan instance tidak relevan ... lihat contoh berikut:

#include <stdio.h>

template<int num>
void bar()
{
    static int baz;
    printf("bar<%i>::baz = %i\n", num, baz++);
}

int main()
{
    bar<1>(); // Output will be 0
    bar<2>(); // Output will be 0
    bar<3>(); // Output will be 0
    bar<1>(); // Output will be 1
    bar<2>(); // Output will be 1
    bar<3>(); // Output will be 1
    bar<1>(); // Output will be 2
    bar<2>(); // Output will be 2
    bar<3>(); // Output will be 2
    return 0;
}

41
+1 untuk keyword static unfortunately has a few different unrelated meanings in C++:)
iammilind

dunia menjadi jauh lebih masuk akal setelah membaca ini, TERIMA KASIH
Erin

Saya suka trik dengan template. Saya tidak sabar untuk mencari alasan untuk menggunakannya.
Tomáš Zato - Reinstate Monica

Adakah yang mendapat referensi untuk "agak berkecil hati demi ruang nama yang tidak disebutkan namanya"?
austinmarton

3
@ austinmarton: Ungkapan "Penggunaan statis untuk menunjukkan 'lokal ke unit terjemahan' ditinggalkan dalam C ++. Gunakan ruang nama yang tidak disebutkan namanya (8.2.5.1)" hadir pada Bahasa Pemrograman C ++ dalam edisi saya (cetakan 10, September 1999) di halaman 819.
6502

2

Variabel statis di dalam fungsi

  • Variabel statis dibuat di dalam fungsi yang disimpan pada memori statis program, bukan di stack.

  • Inisialisasi variabel statis akan dilakukan pada panggilan pertama fungsi.

  • Variabel statis akan mempertahankan nilai dalam beberapa panggilan fungsi

  • Seumur hidup dari variabel statis adalah Program

masukkan deskripsi gambar di sini

Contohnya

#include <iostream>

using namespace std;

class CVariableTesting 
{
    public:
    
    void FuncWithStaticVariable();
    void FuncWithAutoVariable();

};

void CVariableTesting::FuncWithStaticVariable()
{
    static int staticVar = 0; //staticVar is initialised by 0 the first time
    cout<<"Variable Value : "<<staticVar<<endl;
    staticVar++;
}
void CVariableTesting::FuncWithAutoVariable()
{
    int autoVar = 0;
    cout<<"Variable Value : "<<autoVar<<endl;
    autoVar++;
}
    

int main()
{
    CVariableTesting objCVariableTesting;
    cout<<"Static Variable";
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    objCVariableTesting.FuncWithStaticVariable();
    
    cout<<endl;
    cout<<"Auto Variable";
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    objCVariableTesting.FuncWithAutoVariable();
    
    return 0;
}

Output:

Variabel statis

Nilai Variabel: 0
Nilai Variabel: 1
Nilai Variabel: 2
Nilai Variabel: 3
Nilai Variabel: 4

Variabel Otomatis

Nilai Variabel: 0
Nilai Variabel: 0
Nilai Variabel: 0
Nilai Variabel: 0
Nilai Variabel: 0


-2

Jawaban sederhana:

Variabel statis, terlepas dari apakah mereka adalah anggota dari fungsi (non-templated) classatau (non-templated), berperilaku - secara teknis - seperti label global yang cakupannya terbatas pada classfungsi atau.


9
Tidak. Global diinisialisasi pada startup program, statika fungsi diinisialisasi pada penggunaan pertama. Ini perbedaan besar .
6502

Saya tidak berpikir inilah yang terjadi. Namun, ini harus menjadi kompiler khusus.
0xbadf00d

2
Kemudian Anda berpikir salah: 3.6.1 dalam standar C ++ menentukan bahwa konstruksi objek namespace lingkup dengan durasi penyimpanan statis terjadi saat startup; 6.7 (4) menyatakan bahwa secara umum "... variabel tersebut diinisialisasi saat pertama kali kontrol melewati deklarasi; variabel tersebut dianggap diinisialisasi setelah selesainya inisialisasi". Ngomong-ngomong inisialisasi-on-first-use ini sangat berguna untuk mengimplementasikan konstruksi lazy singleton.
6502

3.7.4: "Inisialisasi konstan (3.6.2) dari entitas blok-lingkup dengan durasi penyimpanan statis, jika berlaku, dilakukan sebelum bloknya pertama kali dimasukkan. Implementasi diizinkan untuk melakukan inisialisasi awal variabel ruang lingkup blok lainnya dengan durasi penyimpanan statis atau thread dalam kondisi yang sama bahwa suatu implementasi diizinkan untuk secara inisialisasi menginisialisasi variabel dengan durasi penyimpanan statis atau thread dalam lingkup namespace (3.6.2). Jika tidak, variabel tersebut diinisialisasi ketika kontrol pertama kali melewati deklarasi; "
0xbadf00d

1
Namun cukup mengherankan: 1) untuk inisialisasi konstan itu tidak relevan membahas jika statis lokal dapat diinisialisasi sebelum memasuki blok pertama kali (variabel hanya terlihat di dalam blok dan inisialisasi konstan tidak menghasilkan efek samping); 2) tidak ada dalam posting Anda yang mengatakan tentang inisialisasi konstan; 3) statika lokal sangat berguna untuk inisialisasi non-konstan seperti MyClass& instance(){ static MyClass x("config.ini"); return x; }- implementasi portabel yang valid untuk penggunaan utas tunggal persis karena statika lokal TIDAK hanya seperti global terlepas dari apa yang Anda katakan.
6502
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.