Speicherklassen (C++)Storage classes (C++)

Ein Speicherklasse im Kontext von C++-Variablendeklarationen ist ein Typbezeichner, die die Lebensdauer, Bindung und Speicherort von Objekten steuert.A storage class in the context of C++ variable declarations is a type specifier that governs the lifetime, linkage, and memory location of objects. Ein angegebenes Objekt kann nur eine Speicherklasse haben.A given object can have only one storage class. Variablen, die innerhalb eines Blocks definiert sind, haben automatischen Speicher, wenn nicht anders mithilfe der Bezeichner extern, static oder thread_local angegeben.Variables defined within a block have automatic storage unless otherwise specified using the extern, static, or thread_local specifiers. Automatische Objekte und Variablen haben keine Bindung; sie sind für Code außerhalb des Blocks nicht sichtbar.Automatic objects and variables have no linkage; they are not visible to code outside the block.

NotizenNotes

  1. Die änderbare Schlüsselwort kann als Speicherklassenspezifizierer angesehen werden.The mutable keyword may be considered a storage class specifier. Es ist jedoch nur in der Memberliste einer Klassendefinition verfügbar.However, it is only available in the member list of a class definition.

  2. Visual C++ 2010 und höher: der auto Schlüsselwort ist nicht mehr als eine C++-Speicherklassenspezifizierer, und die register Schlüsselwort ist veraltet.Visual C++ 2010 and later: The auto keyword is no longer a C++ storage-class specifier, and the register keyword is deprecated. Visual Studio 2017 15.7 und höher: (verfügbar mit /std:c ++ 17): die register Schlüsselwort aus der Programmiersprache C++ entfernt.Visual Studio 2017 version 15.7 and later: (available with /std:c++17): The register keyword is removed from the C++ language.

   register int val; // warning C5033: 'register' is no longer a supported storage class

In diesem AbschnittIn this section:

Statischestatic

Das static-Schlüsselwort kann zum Deklarieren von Variablen und Funktionen im globalen Gültigkeitsbereich, Namespace-Gültigkeitsbereich und Klassengültigkeitsbereich verwendet werden.The static keyword can be used to declare variables and functions at global scope, namespace scope, and class scope. Statische Variablen können auch im lokalen Gültigkeitsbereich deklariert werden.Static variables can also be declared at local scope.

Statische Dauer bedeutet, dass das Objekt oder die Variable zugewiesen wird, wenn das Programm gestartet wird. Die Zuweisung wird wieder aufgehoben, wenn das Programm beendet wird.Static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends. Externe Verknüpfung bedeutet, dass der Name der Variablen von außerhalb der Datei sichtbar ist, in der die Variable deklariert wird.External linkage means that the name of the variable is visible from outside the file in which the variable is declared. Umgekehrt bedeutet interne Verknüpfung, dass der Name nicht außerhalb der Datei sichtbar ist, in der die Variable deklariert wird.Conversely, internal linkage means that the name is not visible outside the file in which the variable is declared. Standardmäßig verfügt ein Objekt oder eine Variable, das bzw. die im globalen Namespace definiert wird, über eine statische Dauer und externe Verknüpfung.By default, an object or variable that is defined in the global namespace has static duration and external linkage. Das static-Schlüsselwort kann in folgenden Situationen verwendet werden:The static keyword can be used in the following situations.

  1. Wenn Sie eine Variable oder eine Funktion im Dateibereich (globaler und/oder Namespacebereich) deklarieren, gibt das static-Schlüsselwort die Variable oder Funktion mit interner Verknüpfung an.When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. Wenn Sie eine Variable deklarieren, hat die Variable eine statische Dauer und wird vom Compiler mit dem Wert 0 initialisiert, solange Sie keinen anderen Wert angeben.When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.

  2. Wenn Sie eine Variable in einer Funktion deklarieren, gibt das static-Schlüsselwort an, dass die Variable ihren Status zwischen den Aufrufen der Funktion beibehält.When you declare a variable in a function, the static keyword specifies that the variable retains its state between calls to that function.

  3. Wenn Sie einen Datenmember in einer Klassendeklaration deklarieren, gibt das static-Schlüsselwort an, dass eine Kopie des Members für alle Instanzen der Klasse freigegeben wird.When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. Ein statischer Datenmember muss im Dateibereich definiert sein.A static data member must be defined at file scope. Ein ganzzahliger Datenmember, die Sie als deklarieren const static kann einen Initialisierer haben.An integral data member that you declare as const static can have an initializer.

  4. Wenn Sie eine Memberfunktion in einer Klassendeklaration deklarieren, gibt das static-Schlüsselwort an, dass die Funktion für alle Instanzen der Klasse freigegeben wird.When you declare a member function in a class declaration, the static keyword specifies that the function is shared by all instances of the class. Eine statische Memberfunktion kann nicht auf einen Instanzmember zugreifen, weil die Funktion keinen impliziten this Zeiger aufweist.A static member function cannot access an instance member because the function does not have an implicit this pointer. Um auf einen Instanzmember zuzugreifen, deklarieren Sie die Funktion mit einem Parameter, der ein Instanzzeiger oder -verweis ist.To access an instance member, declare the function with a parameter that is an instance pointer or reference.

  5. Sie können die Member einer Union nicht als statisch deklarieren.You cannot declare the members of a union as static. Allerdings muss eine global deklarierte anonyme Union explizit als static deklariert werden.However, a globally declared anonymous union must be explicitly declared static.

In diesem Beispiel wird gezeigt, wie eine Variable deklariert static in einer Funktion behält ihren Status zwischen den Aufrufen der Funktion.This example shows how a variable declared static in a function retains its state between calls to that function.

// 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

Dieses Beispiel zeigt die Verwendung von static in einer Klasse.This example shows the use of static in a class.

// 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

Dieses Beispiel zeigt eine lokale Variable deklariert static in einer Memberfunktion.This example shows a local variable declared static in a member function. Die statische Variable ist im gesamten Programm verfügbar. Alle Instanzen des Typs verwenden dieselbe Kopie der statischen Variable.The static variable is available to the whole program; all instances of the type share the same copy of the static variable.

// 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

Ab C++11 ist eine statische lokale Variableninitialisierung auf jeden Fall threadsicher.Starting in C++11, a static local variable initialization is guaranteed to be thread-safe. Dieses Feature wird manchmal bezeichnet "magische" static-Objekte.This feature is sometimes called magic statics. Allerdings müssen alle nachfolgende Zuweisungen in einer Multithreadanwendung synchronisiert werden.However, in a multithreaded application all subsequent assignments must be synchronized. Die Thread-sichere statischen Initialisierung-Feature kann deaktiviert werden, mithilfe der /Zc:threadSafeInit- zu vermeiden, erstellen eine Abhängigkeit vom CRT-Flag.The thread-safe static initialization feature can be disabled by using the /Zc:threadSafeInit- flag to avoid taking a dependency on the CRT.

"extern"extern

Objekte und Variablen, die als extern deklariert werden, deklarieren ein Objekt, das in einer anderen Übersetzungseinheit oder in einem einschließenden Bereich mit externer Verknüpfung definiert ist.Objects and variables declared as extern declare an object that is defined in another translation unit or in an enclosing scope as having external linkage.

Deklaration von const Variablen mit der extern -Speicherklasse erzwingt, dass die Variable an eine externe Bindung aufweisen.Declaration of const variables with the extern storage class forces the variable to have external linkage. Eine Initialisierung einer extern const Variable ist in der definierenden Übersetzungseinheit zulässig.An initialization of an extern const variable is allowed in the defining translation unit. Initialisierungen in Übersetzungseinheiten, die keine definierenden Übersetzungseinheiten sind, erzeugen nicht definierte Ergebnisse.Initializations in translation units other than the defining translation unit produce undefined results. Weitere Informationen finden Sie unter mithilfe von "extern" zur Angabe der VerknüpfungFor more information, see Using extern to Specify Linkage

Die /Zc:externConstexpr -Compileroption bewirkt, dass den Compiler anzuwendende externe Verknüpfung Variablen deklariert, indem "extern" Constexpr.The /Zc:externConstexpr compiler option causes the compiler to apply external linkage to variables declared by using extern constexpr. In früheren Versionen von Visual Studio, und standardmäßig oder wenn /Zc:externConstexpr- angegeben ist, wird Visual Studio wendet interne Verknüpfung zu Constexpr Variablen erstellen, selbst wenn die "extern" Schlüsselwort verwendet wird.In earlier versions of Visual Studio, and by default or if /Zc:externConstexpr- is specified, Visual Studio applies internal linkage to constexpr variables even if the extern keyword is used. Die /Zc:externConstexpr Option ist verfügbar in Visual Studio 2017 Update 15,6 ab.The /Zc:externConstexpr option is available starting in Visual Studio 2017 Update 15.6. und ist standardmäßig deaktiviert.and is off by default. Die /permissive-option aktiviert /Zc:externConstexpr nicht.The /permissive- option does not enable /Zc:externConstexpr.

Der folgende Code zeigt zwei extern-Deklarationen, DefinedElsewhere (die sich auf einen Namen bezieht, der in einer anderen Übersetzungseinheit definiert wurde) und DefinedHere (die sich auf einen Namen bezieht, der in einem einschließenden Bereich definiert wurde):The following code shows two extern declarations, DefinedElsewhere (which refers to a name defined in a different translation unit) and DefinedHere (which refers to a name defined in an enclosing scope):

// external.cpp
// DefinedElsewhere is defined in another translation unit
extern int DefinedElsewhere;   
int main() {
   int DefinedHere; 
   {
      // refers to DefinedHere in the enclosing scope
      extern int DefinedHere;
   }
}

Thread_local (C ++ 11)thread_local (C++11)

Auf eine Variable, die mit dem thread_local-Bezeichner deklariert wird, kann nur in dem Thread, in dem sie erstellt wird, zugegriffen werden.A variable declared with the thread_local specifier is accessible only on the thread on which it is created. Die Variable wird erstellt, wenn der Thread erstellt, und gelöscht, wenn der Thread gelöscht wird.The variable is created when the thread is created, and destroyed when the thread is destroyed. Jeder Thread verfügt über eine eigene Kopie der Variable.Each thread has its own copy of the variable. Unter Windows thread_local ist funktionell gleichwertig mit der Microsoft-spezifische __declspec (Thread) Attribut.On Windows, thread_local is functionally equivalent to the Microsoft-specific __declspec( thread ) attribute.

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;
}

Dinge zu beachten Sie die thread_local Bezeichner:Things to note about the thread_local specifier:

  • Dynamisch initialisierte Thread-lokalen Variablen in DLLs können für alle aufrufenden Threads nicht ordnungsgemäß initialisiert werden.Dynamically initialized thread-local variables in DLLs may not be correctly initialized on all calling threads. Weitere Informationen finden Sie unter Thread.For more information, see thread.

  • Die thread_local Bezeichner kann mit kombiniert werden static oder extern.The thread_local specifier may be combined with static or extern.

  • Sie können anwenden thread_local nur auf Datendeklarationen und-Definitionen; thread_local kann nicht für Funktionsdeklarationen oder-Definitionen verwendet werden.You can apply thread_local only to data declarations and definitions; thread_local cannot be used on function declarations or definitions.

  • Sie können thread_local nur für Datenelemente mit statischer Speicherdauer angeben.You can specify thread_local only on data items with static storage duration. Hierzu zählen globale Datenobjekte (sowohl static und extern), lokale statische Objekte sowie statische Datenmember von Klassen.This includes global data objects (both static and extern), local static objects, and static data members of classes. Jede lokale Variable deklariert thread_local ist implizit statisch, wenn keine anderen Speicherklasse angegeben wird; also am Blockbereich thread_local entspricht thread_local static.Any local variable declared thread_local is implicitly static if no other storage class is provided; in other words, at block scope thread_local is equivalent to thread_local static.

  • Sie müssen das thread_local für die Deklaration und Definition eines lokalen Threadobjekts angeben, egal ob die Deklaration und Definition in der gleichen Datei oder in separaten Dateien auftreten.You must specify thread_local for both the declaration and the definition of a thread local object, whether the declaration and definition occur in the same file or separate files.

Unter Windows thread_local ist funktionell gleichwertig mit __declspec(thread) mit dem Unterschied, dass __declspec(thread) kann auf eine Typdefinition angewendet werden und in C-Code gültig ist.On Windows, thread_local is functionally equivalent to __declspec(thread) except that __declspec(thread) can be applied to a type definition and is valid in C code. Verwenden Sie nach Möglichkeit thread_local, da dies ein Teil des C++-Standards ist und daher besser zu potieren ist.Whenever possible, use thread_local because it is part of the C++ standard and is therefore more portable.

Registrierenregister

Visual Studio 2017 15,3 und höher (verfügbar mit /std:c ++ 17): die register Schlüsselwort ist nicht mehr unterstützte Speicherklasse.Visual Studio 2017 version 15.3 and later (available with /std:c++17): The register keyword is no longer a supported storage class. Das Schlüsselwort ist immer noch in der Standard für zukünftige Verwendung reserviert.The keyword is still reserved in the standard for future use.

   register int val; // warning C5033: 'register' is no longer a supported storage class

Beispiel: automatische im Vergleich zu statischen InitialisierungExample: automatic vs. static initialization

Ein lokales automatisches Objekt oder eine lokale automatische Variable wird jedes Mal initialisiert, wenn die Ablaufsteuerung ihre Definition erreicht.A local automatic object or variable is initialized every time the flow of control reaches its definition. Ein lokales automatisches Objekt oder eine lokale automatische Variable wird erstmalig initialisiert, wenn die Ablaufsteuerung ihre Definition erreicht.A local static object or variable is initialized the first time the flow of control reaches its definition.

Betrachten Sie das folgende Beispiel, in dem eine Klasse definiert wird, die die Initialisierung und Beschädigung von Objekten protokolliert und dann drei Objekte, I1, I2 und I3, definiert:Consider the following example, which defines a class that logs initialization and destruction of objects and then defines three objects, I1, I2, and 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

In diesem Beispiel wird veranschaulicht, wie und wann die Objekte I1, I2, und I3 werden initialisiert und zerstört werden.This example demonstrates how and when the objects I1, I2, and I3 are initialized and when they are destroyed.

Es gibt einige Punkte zu beachten über das Programm:There are several points to note about the program:

  • Erstens werden I1 und I2 automatisch beschädigt, wenn die Ablaufsteuerung den Block beendet, in dem sie definiert sind.First, I1 and I2 are automatically destroyed when the flow of control exits the block in which they are defined.

  • Zweitens ist es in C++ nicht notwendig, Objekte oder Variablen am Anfang eines Blocks zu deklarieren.Second, in C++, it is not necessary to declare objects or variables at the beginning of a block. Außerdem werden diese Objekte nur initialisiert, wenn die Ablaufsteuerung deren Definitionen erreicht.Furthermore, these objects are initialized only when the flow of control reaches their definitions. (I2 und I3 sind Beispiele solcher Definitionen.) Die Ausgabe zeigt eindeutig, wann sie initialisiert werden.(I2 and I3 are examples of such definitions.) The output shows exactly when they are initialized.

  • Des Weiteren behalten statische lokale Variablen wie I3 ihre Werte für die Dauer des Programms bei, werden jedoch beschädigt, sobald das Programm beendet wird.Finally, static local variables such as I3 retain their values for the duration of the program, but are destroyed as the program terminates.

Siehe auchSee Also

Deklarationen und DefinitionenDeclarations and Definitions