Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A C++ változódeklarációk környezetében található tárolási osztály egy típuskijelölő, amely szabályozza az objektumok élettartamát, összekapcsolását és memóriahelyét. Egy adott objektumnak csak egy tárosztálya lehet. A blokkon belül definiált változók automatikus tárolóval rendelkeznek, kivéve, ha a extern, staticvagy thread_local a kijelölők másként vannak megadva. Az automatikus objektumok és változók nincsenek összekapcsolva; a blokkon kívüli kód nem látható. A rendszer automatikusan lefoglalja a memóriát, amikor a végrehajtás belép a blokkba, és a blokk kilépésekor megszűnik.
Jegyzetek
A
mutablekulcsszó tárolóosztály-meghatározónak tekinthető. Ez azonban csak egy osztálydefiníció taglistájában érhető el.Visual Studio 2010 és újabb verziók: A
autokulcsszó már nem C++ tárosztály-meghatározó, és aregisterkulcsszó elavult. Visual Studio 2017 15.7-es és újabb verzió: (módban és később érhető el/std:c++17): Aregisterkulcsszó el lesz távolítva a C++ nyelvről. Használata diagnosztikai üzenetet okoz:// 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
A static kulcsszó használható változók és függvények globális hatókörben, névtér- és osztályhatókörben történő deklarálásához. A statikus változók helyi hatókörben is deklarálhatók.
A statikus időtartam azt jelenti, hogy az objektum vagy változó a program indításakor lesz lefoglalva, és a program befejezésekor felszabadítja. A külső kapcsolat azt jelenti, hogy a változó neve azon a fájlon kívülről látható, ahol a változó deklarálva van. Ezzel szemben a belső kapcsolat azt jelenti, hogy a név nem látható azon a fájlon kívül, amelyben a változó deklarálva van. Alapértelmezés szerint egy globális névtérben definiált objektum vagy változó statikus időtartammal és külső kapcsolattal rendelkezik. A static kulcsszó a következő helyzetekben használható.
Ha egy változót vagy függvényt fájlhatókörben deklarál (globális és/vagy névtér-hatókör), a
statickulcsszó azt határozza meg, hogy a változó vagy függvény belső kapcsolatokkal rendelkezik. Változó deklarálásakor a változó statikus időtartamú, a fordító pedig 0 értékre inicializálja, hacsak nem ad meg másik értéket.Ha egy függvényben deklarál egy változót, a
statickulcsszó azt határozza meg, hogy a változó megtartsa az állapotát a függvény hívásai között.Amikor egy osztálydeklarációban adattagot deklarál, a
statickulcsszó azt határozza meg, hogy a tag egy példányát az osztály összes példánya megosztja. Azstaticadattagot a fájl hatókörében kell definiálni. Egy inicializálóként deklaráltconst static, integrált adattag.Amikor egy tagfüggvényt osztálydeklarációban deklarál, a
statickulcsszó azt határozza meg, hogy a függvényt az osztály összes példánya megosztja. Astatictagfüggvények nem férnek hozzá a példánytagokhoz, mert a függvény nem rendelkezik implicitthismutatóval. Egy példánytag eléréséhez deklarálja a függvényt egy olyan paraméterrel, amely egy példánymutató vagy hivatkozás.A tagok
unionnem deklarálhatók a következőkéntstatic: . A globálisan deklarált névtelennekunionazonban explicit módon kell deklarálniastatic.
Ez a példa bemutatja, hogy egy függvényben deklarált static változó hogyan őrzi meg az állapotát a függvény hívásai között.
// 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
Ez a példa egy static osztály használatát mutatja be.
// 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
Az alábbi példa egy tagfüggvényben deklarált static helyi változót mutat be. A static változó a teljes program számára elérhető; a típus összes példánya ugyanazzal a változóval rendelkezik static .
// 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
A C++11-től kezdve a static helyi változó inicializálása garantáltan szálbiztos lesz. Ezt a funkciót néha mágikus statikusnak is nevezik. Többszálú alkalmazásokban azonban minden további hozzárendelést szinkronizálni kell. A szálbiztos statikus inicializálási funkció letiltható a /Zc:threadSafeInit- jelölő használatával, hogy elkerülje a CRT-függőséget.
extern
A deklarált objektumok és változók deklarált extern objektumként vannak meghatározva egy másik fordítási egységben vagy egy olyan hatókörben, amely külső kapcsolatokkal rendelkezik. További információkért lásd extern a fordítási egységeket és a csatolást.
thread_local (C++11)
A megadóval thread_local deklarált változó csak azon a szálon érhető el, amelyen létrehozta. A változó a szál létrehozásakor jön létre, és a szál megsemmisítésekor megsemmisül. Minden szál saját másolatot készít a változóról. Windows thread_local rendszeren funkcionálisan egyenértékű a Microsoft-specifikus __declspec( thread ) attribútummal.
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;
}
A megadóval kapcsolatos thread_local tudnivalók:
Előfordulhat, hogy a dll-ekben a dinamikusan inicializált szál helyi változói nem inicializálhatók megfelelően az összes hívószálon. További információért lásd
thread.A
thread_localkijelölő kombinálható a következővelstatic: vagyextern.Csak adatdeklarációkra és definíciókra alkalmazható
thread_local;thread_localfüggvénydeklarációkban és definíciókban nem használható.Csak statikus tárolási időtartamú adatelemeket adhat meg
thread_local, amelyek globális adatobjektumokat (mindkettőtstaticés), helyi statikus objektumokat ésexternosztályok statikus adattagjait is magukban foglalják. A deklarált helyi változók implicit módon statikusak, ha nem adthread_localmeg más tárolási osztályt, más szóval a blokk hatókörethread_localegyenértékű athread_local static.Meg kell adnia
thread_localmind a deklarációt, mind a szál helyi objektumának definícióját, függetlenül attól, hogy a deklaráció és a definíció ugyanabban a fájlban vagy különálló fájlokban történik-e.Nem javasoljuk, hogy változókat használjon
thread_locala következővelstd::launch::async: . További információ:<future>függvények.
Windows rendszeren funkcionálisan egyenértékű __declspec(thread) azzal, thread_local hogy *__declspec(thread)a * típusdefinícióra alkalmazható, és C-kódban érvényes. Amikor csak lehetséges, használja thread_local , mert a C++ szabvány része, ezért hordozhatóbb.
regiszter
Visual Studio 2017 15.3-s és újabb verzió (módban és újabb verziókban /std:c++17 érhető el): A register kulcsszó már nem támogatott tárolási osztály. Használata diagnosztikát okoz. A kulcsszó továbbra is a szabványban van fenntartva későbbi használatra.
register int val; // warning C5033: 'register' is no longer a supported storage class
Példa: automatikus és statikus inicializálás
A helyi automatikus objektum vagy változó minden alkalommal inicializálódik, amikor a vezérlőfolyamat eléri a definícióját. A helyi statikus objektumok vagy változók inicializálása akkor történik, amikor a vezérlőfolyamat első alkalommal eléri a definícióját.
Vegyük az alábbi példát, amely egy olyan osztályt határoz meg, amely naplózza az objektumok inicializálását és megsemmisítését, majd definiál három objektumot, I1I2ésI3:
// 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
Ez a példa bemutatja, hogyan és mikor vannak inicializálva és megsemmisítve az objektumokI1I2I3.
A programról több megjegyzést is érdemes megjegyezni:
Először is,
I1ésI2automatikusan megsemmisül, amikor a vezérlési folyamat kilép a blokkból, amelyben definiálva vannak.Másodszor, a C++-ban nem szükséges objektumokat vagy változókat deklarálni a blokk elején. Továbbá ezek az objektumok csak akkor inicializálódnak, ha a vezérlőfolyamat eléri a definícióikat. (
I2ésI3példák ezekre a definíciókra.) A kimenet pontosan akkor jelenik meg, amikor inicializálva vannak.Végül a statikus helyi változók, például
I3megtartják az értékeiket a program futtatásakor, de a program leállásakor elvesznek.