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

Ein Speicherklasse im Kontext von C++-Variablendeklarationen ist ein Typbezeichner, der 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 haben automatischen Speicher, sofern nicht anders angegeben, mit der "extern", statische, oder thread_local Spezifizierer.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 als Speicherklassenspezifizierer angesehen werden kann.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 automatisch Schlüsselwort ist nicht mehr eine C++-Speicherklassenspezifizierer, und die registrieren 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 Version 15.7 und höher: (verfügbar mit /Std: c ++ 17): die registrieren 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

Die statische -Schlüsselwort zum Deklarieren von Variablen und Funktionen im globalen Gültigkeitsbereich, Namespace-Gültigkeitsbereich und Klassengültigkeitsbereich verwendet werden kann.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. Die statische -Schlüsselwort kann in den folgenden Situationen verwendet werden.The static keyword can be used in the following situations.

  1. Wenn Sie deklarieren eine Variable oder Funktion im Dateibereich (globaler und/oder Namespacebereich), wird die statische -Schlüsselwort Gibt an, dass die Variable oder Funktion intern verknüpft ist.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 die statische -Schlüsselwort Gibt 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 die statische -Schlüsselwort Gibt an, dass alle Instanzen der Klasse eine Kopie des Elements 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 statische 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 die statische -Schlüsselwort Gibt an, dass die Funktion 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, da die Funktion einen impliziten keine dies Zeiger.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 eine global deklarierte anonyme Union explizit deklariert werden muss statische.However, a globally declared anonymous union must be explicitly declared static.

Dieses Beispiel zeigt, wie eine Variable deklariert statische in einer Funktion behält den Zustand zwischen 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 statische 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 statische 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 genannt magic Statics.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 Funktion für threadsichere statische Initialisierung kann deaktiviert werden, mithilfe der /Zc:threadSafeInit- Flag, um zu vermeiden, erstellen eine Abhängigkeit vom CRT.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" 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 dem "extern" -Speicherklasse erzwingt, dass die Variable an eine externe Bindung verfügen.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 veranlasst 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 internen Verknüpfung, "constexpr" Variablen auch dann, wenn die "extern" -Schlüsselwort wird verwendet.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. / Zc: externconstexpr aktiviert der PERMISSIVE nicht.The /permissive- option does not enable /Zc:externConstexpr.

Der folgende Code zeigt zwei "extern" Deklarationen DefinedElsewhere (die bezieht sich auf einen Namen, die in einer anderen Übersetzungseinheit definiert) und DefinedHere (die bezieht sich auf einen Namen in einem einschließenden Bereich definiert):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. Auf 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;
}

Punkte zu beachten 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 statische 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 statische 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; das heißt, im 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 threadlokalen Objekts 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.

Auf 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 Version 15.3 und höher (verfügbar mit /Std: c ++ 17): die registrieren 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 die 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 zerstört, 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 zerstört, 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