Kelas penyimpanan
Kelas penyimpanan dalam konteks deklarasi variabel C++ adalah penentu jenis yang mengatur masa pakai, tautan, dan lokasi memori objek. Objek tertentu hanya dapat memiliki satu kelas penyimpanan. Variabel yang ditentukan dalam blok memiliki penyimpanan otomatis kecuali ditentukan lain menggunakan extern
, , static
atau thread_local
penentu. Objek dan variabel otomatis tidak memiliki tautan; mereka tidak terlihat oleh kode di luar blok. Memori dialokasikan untuk mereka secara otomatis saat eksekusi memasuki blok, dan tidak dialokasikan saat blok keluar.
Catatan
Kata
mutable
kunci dapat dianggap sebagai penentu kelas penyimpanan. Namun, hanya tersedia dalam daftar anggota definisi kelas.Visual Studio 2010 dan yang lebih baru: Kata
auto
kunci bukan lagi penentu kelas penyimpanan C++, danregister
kata kunci tidak digunakan lagi. Visual Studio 2017 versi 15.7 dan yang lebih baru: (tersedia dalam/std:c++17
mode dan yang lebih baru): Kataregister
kunci dihapus dari bahasa C++. Penggunaannya menyebabkan pesan diagnostik:// c5033.cpp // compile by using: cl /c /std:c++17 c5033.cpp register int value; // warning C5033: 'register' is no longer a supported storage class
static
Kata static
kunci dapat digunakan untuk mendeklarasikan variabel dan fungsi pada cakupan global, cakupan namespace layanan, dan cakupan kelas. Variabel statis juga dapat dideklarasikan pada cakupan lokal.
Durasi statis berarti bahwa objek atau variabel dialokasikan ketika program dimulai dan dibatalkan alokasinya ketika program berakhir. Tautan eksternal berarti bahwa nama variabel terlihat dari luar file tempat variabel dideklarasikan. Sebaliknya, tautan internal berarti bahwa nama tidak terlihat di luar file tempat variabel dideklarasikan. Secara default, objek atau variabel yang ditentukan dalam namespace layanan global memiliki durasi statis dan tautan eksternal. Kata static
kunci dapat digunakan dalam situasi berikut.
Saat Anda mendeklarasikan variabel atau fungsi pada cakupan file (cakupan global dan/atau namespace),
static
kata kunci menentukan bahwa variabel atau fungsi memiliki tautan internal. Saat Anda mendeklarasikan variabel, variabel memiliki durasi statis dan pengkompilasi menginisialisasinya ke 0 kecuali Anda menentukan nilai lain.Saat Anda mendeklarasikan variabel dalam fungsi,
static
kata kunci menentukan bahwa variabel mempertahankan statusnya di antara panggilan ke fungsi tersebut.Saat Anda mendeklarasikan anggota data dalam deklarasi kelas,
static
kata kunci menentukan bahwa satu salinan anggota dibagikan oleh semua instans kelas.static
Anggota data harus didefinisikan pada cakupan file. Anggota data integral yang Anda nyatakan sebagaiconst static
dapat memiliki inisialisasi.Saat Anda mendeklarasikan fungsi anggota dalam deklarasi kelas,
static
kata kunci menentukan bahwa fungsi dibagikan oleh semua instans kelas. Fungsistatic
anggota tidak dapat mengakses anggota instans karena fungsi tidak memiliki penunjuk implisitthis
. Untuk mengakses anggota instans, deklarasikan fungsi dengan parameter yang merupakan penunjuk instans atau referensi.Anda tidak dapat mendeklarasikan anggota
union
sebagaistatic
. Namun, anonimunion
yang dinyatakan secara global harus secara eksplisit dinyatakanstatic
.
Contoh ini menunjukkan bagaimana variabel yang dideklarasikan static
dalam fungsi mempertahankan statusnya di antara panggilan ke fungsi tersebut.
// static1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void showstat( int curr ) {
static int nStatic; // Value of nStatic is retained
// between each function call
nStatic += curr;
cout << "nStatic is " << nStatic << endl;
}
int main() {
for ( int i = 0; i < 5; i++ )
showstat( i );
}
nStatic is 0
nStatic is 1
nStatic is 3
nStatic is 6
nStatic is 10
Contoh ini menunjukkan penggunaan static
di kelas.
// static2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
class CMyClass {
public:
static int m_i;
};
int CMyClass::m_i = 0;
CMyClass myObject1;
CMyClass myObject2;
int main() {
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
myObject1.m_i = 1;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
myObject2.m_i = 2;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
CMyClass::m_i = 3;
cout << myObject1.m_i << endl;
cout << myObject2.m_i << endl;
}
0
0
1
1
2
2
3
3
Contoh berikut menunjukkan variabel lokal yang dideklarasikan static
dalam fungsi anggota. Variabel static
tersedia untuk seluruh program; semua instans jenis berbagi salinan variabel yang static
sama.
// static3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
struct C {
void Test(int value) {
static int var = 0;
if (var == value)
cout << "var == value" << endl;
else
cout << "var != value" << endl;
var = value;
}
};
int main() {
C c1;
C c2;
c1.Test(100);
c2.Test(100);
}
var != value
var == value
Mulai dari C++11, static
inisialisasi variabel lokal dijamin aman untuk utas. Fitur ini terkadang disebut statis ajaib. Namun, dalam aplikasi multithreaded semua penugasan berikutnya harus disinkronkan. Fitur inisialisasi statis aman utas dapat dinonaktifkan dengan menggunakan /Zc:threadSafeInit-
bendera untuk menghindari mengambil dependensi pada CRT.
extern
Objek dan variabel dideklarasikan sebagai extern
mendeklarasikan objek yang didefinisikan dalam unit terjemahan lain atau dalam cakupan penutup sebagai memiliki tautan eksternal. Untuk informasi selengkapnya, lihat extern
dan Unit terjemahan dan tautan.
thread_local
(C++11)
Variabel yang dideklarasikan dengan penentu thread_local
hanya dapat diakses pada utas tempat variabel dibuat. Variabel dibuat ketika utas dibuat, dan dihancurkan ketika utas dihancurkan. Setiap utas memiliki salinan variabelnya sendiri. Di Windows, thread_local
secara fungsional setara dengan atribut khusus __declspec( thread )
Microsoft.
thread_local float f = 42.0; // Global namespace. Not implicitly static.
struct S // cannot be applied to type definition
{
thread_local int i; // Illegal. The member must be static.
thread_local static char buf[10]; // OK
};
void DoSomething()
{
// Apply thread_local to a local variable.
// Implicitly "thread_local static S my_struct".
thread_local S my_struct;
}
Hal-hal yang perlu diperhatikan tentang penentu thread_local
:
Variabel thread-local yang diinisialisasi secara dinamis di DLL mungkin tidak diinisialisasi dengan benar pada semua utas panggilan. Untuk informasi selengkapnya, lihat
thread
.Penentu
thread_local
dapat dikombinasikan denganstatic
atauextern
.Anda hanya dapat menerapkan
thread_local
ke deklarasi dan definisi data;thread_local
tidak dapat digunakan pada deklarasi atau definisi fungsi.Anda hanya dapat menentukan
thread_local
item data dengan durasi penyimpanan statis, yang mencakup objek data global (baikstatic
danextern
), objek statis lokal, dan anggota data statis kelas. Setiap variabel lokal yang dideklarasikanthread_local
secara implisit statis jika tidak ada kelas penyimpanan lain yang disediakan; dengan kata lain, pada cakupanthread_local
blok setara denganthread_local static
.Anda harus menentukan
thread_local
untuk deklarasi dan definisi objek lokal utas, apakah deklarasi dan definisi terjadi dalam file yang sama atau file terpisah.Kami tidak menyarankan Anda menggunakan
thread_local
variabel denganstd::launch::async
. Untuk informasi selengkapnya, lihat<future>
fungsi.
Di Windows, thread_local
secara fungsional __declspec(thread)
setara dengan kecuali bahwa *__declspec(thread)
* dapat diterapkan ke definisi jenis dan valid dalam kode C. Jika memungkinkan, gunakan thread_local
karena ini adalah bagian dari standar C++ dan oleh karena itu lebih portabel.
register
Visual Studio 2017 versi 15.3 dan yang lebih baru (tersedia dalam /std:c++17
mode dan yang lebih baru): Kata register
kunci bukan lagi kelas penyimpanan yang didukung. Penggunaannya menyebabkan diagnostik. Kata kunci masih dicadangkan dalam standar untuk digunakan di masa mendatang.
register int val; // warning C5033: 'register' is no longer a supported storage class
Contoh: inisialisasi statis vs. otomatis
Objek atau variabel otomatis lokal diinisialisasi setiap kali alur kontrol mencapai definisinya. Objek atau variabel statis lokal diinisialisasi saat pertama kali alur kontrol mencapai definisinya.
Pertimbangkan contoh berikut, yang menentukan kelas yang mencatat inisialisasi dan penghancuran objek lalu menentukan tiga objek, I1
, , I2
dan I3
:
// initialization_of_objects.cpp
// compile with: /EHsc
#include <iostream>
#include <string.h>
using namespace std;
// Define a class that logs initializations and destructions.
class InitDemo {
public:
InitDemo( const char *szWhat );
~InitDemo();
private:
char *szObjName;
size_t sizeofObjName;
};
// Constructor for class InitDemo
InitDemo::InitDemo( const char *szWhat ) :
szObjName(NULL), sizeofObjName(0) {
if ( szWhat != 0 && strlen( szWhat ) > 0 ) {
// Allocate storage for szObjName, then copy
// initializer szWhat into szObjName, using
// secured CRT functions.
sizeofObjName = strlen( szWhat ) + 1;
szObjName = new char[ sizeofObjName ];
strcpy_s( szObjName, sizeofObjName, szWhat );
cout << "Initializing: " << szObjName << "\n";
}
else {
szObjName = 0;
}
}
// Destructor for InitDemo
InitDemo::~InitDemo() {
if( szObjName != 0 ) {
cout << "Destroying: " << szObjName << "\n";
delete szObjName;
}
}
// Enter main function
int main() {
InitDemo I1( "Auto I1" ); {
cout << "In block.\n";
InitDemo I2( "Auto I2" );
static InitDemo I3( "Static I3" );
}
cout << "Exited block.\n";
}
Initializing: Auto I1
In block.
Initializing: Auto I2
Initializing: Static I3
Destroying: Auto I2
Exited block.
Destroying: Auto I1
Destroying: Static I3
Contoh ini menunjukkan bagaimana dan kapan objek I1
, , I2
dan I3
diinisialisasi dan ketika dihancurkan.
Ada beberapa poin yang perlu diperhatikan tentang program ini:
Pertama,
I1
danI2
secara otomatis dihancurkan ketika alur kontrol keluar dari blok tempat mereka ditentukan.Kedua, di C++, tidak perlu mendeklarasikan objek atau variabel di awal blok. Selain itu, objek ini hanya diinisialisasi ketika alur kontrol mencapai definisinya. (
I2
danI3
merupakan contoh definisi tersebut.) Output menunjukkan persis kapan mereka diinisialisasi.Akhirnya, variabel lokal statis seperti
I3
mempertahankan nilainya saat program berjalan, tetapi dihancurkan saat program berakhir.
Baca juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk