wake-up-neo.net

Statische globale Variablen in C++

Ich möchte mit der Malloc-Methode ein Array von ganzen Zahlen erstellen. Ich möchte, dass dieses Array global ist und überall in meinem Programm verwendet wird. Ich habe Code in eine Headerdatei eingefügt, die so aussah:

static int *pieces;

Dann habe ich eine Funktion, die es mit Zahlen füllt, die ich dort haben möchte. Die Funktion befindet sich in einem Namespace und der Namespace ist in einer eigenen CPP-Datei implementiert. Ich importiere jedoch die Header-Datei in main.c und rufe die Funktion aus dem Namespace auf, der das Array wie folgt erstellt:

pieces = malloc(sizeof(int) * 128);

Wenn ich jedoch versuche, auf Zahlen im Array in main zuzugreifen (nachdem ich die Funktion aufgerufen habe, mit der mein Array erstellt wird), stürzt es ab und sagt, dass pieces nicht initialisiert wurde. Aber in der Funktion, die ich habe, kann ich sie erstellen und die Zahlen darin gut manipulieren. Ich hatte den Eindruck, dass durch das Erstellen von Stücken als statische Variable jedes Mal, wenn sich irgendwo eine Funktion ändert (oder setzt), dies die Verwendung der Variablen an einer beliebigen Stelle beeinflusst. Im Grunde versuche ich zu sagen, warum erscheinen Stücke in main nicht gesetzt, obwohl ich sie in einer von mir genannten Funktion eingestellt habe?

25
Christian Daley

Static ist ein Schlüsselwort mit vielen Bedeutungen. In diesem Fall bedeutet es nicht global (Paraphrasierung).

Dies bedeutet, dass jede .cpp-Datei eine eigene Kopie der Variablen hat. Wenn Sie also in main.cpp initialisieren, wird NUR in main.cpp initialisiert. Die anderen Dateien haben es noch nicht initialisiert. 

Um dies zu beheben, müssen Sie zunächst das Schlüsselwort static entfernen. Das würde das Problem "Mehrere Definitionen" verursachen. Um dies zu beheben, sollten Sie die Variable in einer .cpp-Datei definieren und sie nur extern in einer Header-Datei deklarieren.


Bearbeiten: Sie weisen nur Speicherplatz zu, zählt nicht als Initialisierung. Sie müssen den Speicher nach der Zuweisung auf 0 initialisieren.

Sie können new int[128]() anstelle Ihrer ausführlicheren malloc-Syntax verwenden, und dies würde auch Initialisierung durchführen sein. Oder Sie können die einfache Straße nehmen (das ist, wozu es da ist) und std::vector verwenden.

52
Karthik T

Der Schlüssel ist folgender:

static int *pieces;

Sie sagten, Sie stecken das in Ihre Kopfzeile. Dies ist nicht der Weg, um ein Symbol zu exportieren. Jede Datei, die den Header enthält, erhält eine eigene statische Version eines nicht initialisierten Zeigers mit dem Namen pieces.

Stattdessen fügen Sie dies in Ihre Kopfzeile ein:

extern int *pieces;

extern int init_pieces();

Und in der Quelldatei machen Sie folgendes:

static const size_t num_pieces = 128;

int *pieces = 0;

int init_pieces()
{
    pieces = malloc( num_pieces * sizeof(int) );
    return pieces != NULL;
}

Wenn Sie nun Ihren Header einschließen, weiß Ihre Quelldatei, dass sie pieces von einem anderen Ort erhält, und wartet, bis der Linker die Position ermittelt. Ich habe auch eine 'init'-Funktion für das Array vorgeschlagen. Ich habe jedoch keine 'Release'-Funktion eingebaut.

Beachten Sie, dass dies alles C ist, nicht C++. Wenn Sie C++ verwenden, sollten Sie new oder besser noch eine vector verwenden.

Beachten Sie bei der Verwendung von Statik in C++ Folgendes: C++ statische Initialisierungsreihenfolge

15
paddy

Im C++ 17-Standard können Sie anstelle von static den inline-Bezeichner verwenden. Für Variablen bedeutet dies, dass jede Objekteinheit über eine Kopie der Variablen verfügt, der Linker wählt jedoch nur eine davon aus ..__ Oder, wie in cppreference angegeben:

Eine Inline-Funktion oder Inline-Variable (seit C++ 17) hat folgendes Eigenschaften:

1) Es kann mehr als eine Definition einer Inline geben Funktion oder Variable (seit C++ 17) im Programm, solange jedes Definition erscheint in einer anderen Übersetzungseinheit und (für nicht statische Inline-Funktionen und -Variablen (seit C++ 17)) sind alle Definitionen identisch. Zum Beispiel eine Inline-Funktion oder eine Inline-Variable (seit C++ 17) kann in einer Header-Datei definiert werden, die # include'd in .__ ist. mehrere Quelldateien.

2) Die Definition einer Inline-Funktion oder Variable (seit C++ 17) muss in der Übersetzungseinheit vorhanden sein, wobei es wird darauf zugegriffen (nicht unbedingt vor dem Zugangspunkt).

3) Eine Inline-Funktion oder -Variable (seit C++ 17) mit externer Verknüpfung (z. B. nicht statisch deklariert) weist die folgenden zusätzlichen Eigenschaften auf:

1) It must be declared inline in every translation unit.

2) It has the same address in every translation unit.

Unterstützt in ( source ):

  • MSVC seit Version 19.12 (VS 2017 15.5)
  • GCC 7
  • Clang 3.9
  • ICC 18.0

In diesem Fall bedeutet dies, dass Sie ersetzen können

static int *pieces;

mit 

inline int *pieces;
1
topin89

Für Hochleistungscode auf verschiedenen Architekturen möchten Sie möglicherweise eine malloc-y-Zuordnung anstelle einer generischen neuen. Das liegt daran, dass Sie es mit etwas wie mymalloc () einwickeln und dann architekturabhängige Funktionen verwenden würden, z. B. Funktionen, die die richtige Ausrichtung implementieren, um Cache-Fehler zu vermeiden und andere nützliche Funktionen des Hardwareherstellers wie IBM (Bluegene) oder Intel (MIC). Alle diese optimierten Zuordnungsroutinen haben das Malloc-Typ-Framework.

1
Joel Giedt