Bagikan melalui


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, , staticatau 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++, dan register 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): Kata register 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.

  1. 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.

  2. Saat Anda mendeklarasikan variabel dalam fungsi, static kata kunci menentukan bahwa variabel mempertahankan statusnya di antara panggilan ke fungsi tersebut.

  3. 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 sebagai const static dapat memiliki inisialisasi.

  4. Saat Anda mendeklarasikan fungsi anggota dalam deklarasi kelas, static kata kunci menentukan bahwa fungsi dibagikan oleh semua instans kelas. Fungsi static anggota tidak dapat mengakses anggota instans karena fungsi tidak memiliki penunjuk implisit this . Untuk mengakses anggota instans, deklarasikan fungsi dengan parameter yang merupakan penunjuk instans atau referensi.

  5. Anda tidak dapat mendeklarasikan anggota union sebagai static. Namun, anonim union yang dinyatakan secara global harus secara eksplisit dinyatakan static.

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 dengan static atau extern.

  • 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 (baik static dan extern), objek statis lokal, dan anggota data statis kelas. Setiap variabel lokal yang dideklarasikan thread_local secara implisit statis jika tidak ada kelas penyimpanan lain yang disediakan; dengan kata lain, pada cakupan thread_local blok setara dengan thread_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 dengan std::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, , I2dan 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, , I2dan I3 diinisialisasi dan ketika dihancurkan.

Ada beberapa poin yang perlu diperhatikan tentang program ini:

  • Pertama, I1 dan I2 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 dan I3 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

Deklarasi dan Definisi