web-dev-qa-db-fra.com

Variables globales statiques en C++

Je voudrais faire un tableau de nombres entiers via la méthode malloc. Je veux que ce tableau soit global et puisse être utilisé n’importe où dans mon programme. J'ai mis le code dans un fichier d'en-tête qui ressemblait à ceci:

static int *pieces;

Ensuite, j'ai une fonction qui la remplit avec les nombres que je veux là. La fonction est dans un espace de noms et l'espace de noms est implémenté dans son propre fichier .cpp. Cependant, j'importe le fichier d'en-tête dans main.c et appelle la fonction à partir de l'espace de noms qui crée le tableau, comme suit:

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

Mais lorsque j'essaie d'accéder aux numéros du tableau dans main (après avoir appelé la fonction qui crée mon tableau), il se bloque et indique que les pièces ne sont pas initialisées. Mais dans la fonction que j'ai, je peux le créer et bien manipuler les nombres. J'avais l'impression qu'en faisant des pièces une variable statique, chaque fois qu'une fonction change (ou la définit) n'importe où, cela affectera l'utilisation de la variable n'importe où. Essentiellement, ce que j'essaie de dire, c'est pourquoi les morceaux semblent non définis dans la fenêtre principale, même si je les ai placés dans une fonction que j'ai appelée

25
Christian Daley

Static est un mot clé ayant plusieurs significations. Dans ce cas particulier, cela signifie non global (paraphrasant)

Cela signifie que chaque fichier .cpp a sa propre copie de la variable. Ainsi, lorsque vous initialisez dans main.cpp, il est initialisé UNIQUEMENT dans main.cpp. Les autres fichiers l'ont toujours non initialisé. 

La première chose à faire serait de supprimer le mot clé static. Cela provoquerait le "problème de définitions multiples". Pour résoudre ce problème, vous devez définir la variable dans un fichier .cpp et simplement extern la déclarer dans un fichier d’en-tête.


Edit: vous ne lui allouez que de la mémoire, ne compte pas comme initialisation. Vous devez initialiser la mémoire à 0 après l’affectation.

Vous pouvez utiliser new int[128]() à la place de votre syntaxe plus détaillée malloc, ce qui vous permettrait également de initialiser Ou vous pouvez prendre la route facile (c'est ce que son là pour) et utiliser std::vector

52
Karthik T

La clé est la suivante:

static int *pieces;

Vous avez dit que vous avez mis cela dans votre en-tête. Ce n'est pas le moyen d'exporter un symbole. Tout fichier comprenant l'en-tête aura sa propre version statique d'un pointeur non initialisé appelé pieces.

Au lieu de cela, vous mettez ceci dans votre en-tête:

extern int *pieces;

extern int init_pieces();

Et dans le fichier source, vous faites ceci:

static const size_t num_pieces = 128;

int *pieces = 0;

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

Maintenant, lorsque vous incluez votre en-tête, votre fichier source saura obtenir pieces ailleurs et attendra que l'éditeur de liens calcule où. J'ai également suggéré une fonction 'init' pour le tableau. Je n'ai cependant pas mis de fonction 'release' dans.

Notez que tout cela est en C, pas en C++. Si vous utilisez C++, vous devriez vraiment utiliser new ou mieux encore, utilisez un vector.

De même, lors de l'utilisation de la statique en C++, tenez compte de ceci: Ordre d'initialisation statique C++

15
paddy

En standard C++ 17, vous pouvez utiliser le spécificateur inline au lieu de statique. Pour les variables, cela signifie que chaque unité d'objet aura une copie de la variable, mais l'éditeur de liens n'en choisira qu'une seule ..__ Ou, comme indiqué dans cppreference :

Une fonction inline ou une variable inline (depuis C++ 17) a les propriétés suivantes Propriétés:

1) Il peut y avoir plus d'une définition d'un inline fonction ou variable (depuis C++ 17) dans le programme aussi longtemps que chaque definition apparaît dans une unité de traduction différente et (pour les fonctions et variables inline non statiques (depuis C++ 17)), toutes les définitions sont identique. Par exemple, une fonction en ligne ou une variable en ligne (depuis C++ 17) peut être défini dans un fichier d’en-tête # include'd in plusieurs fichiers sources.

2) La définition d'une fonction en ligne ou variable (depuis C++ 17) doit être présente dans l'unité de traduction où on y accède (pas nécessairement avant le point d'accès).

3) Une fonction ou une variable en ligne (depuis C++ 17) avec une liaison externe (par exemple, . Non déclarée statique) possède les propriétés supplémentaires suivantes:

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

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

Pris en charge dans ( source ):

  • MSVC depuis la version 19.12 (VS 2017 15.5)
  • GCC 7
  • Clang 3.9
  • ICC 18.0

Dans ce cas, cela signifie que vous pouvez remplacer

static int *pieces;

avec 

inline int *pieces;
1
topin89

Pour obtenir du code haute performance sur diverses architectures, vous souhaiterez peut-être une allocation malloc-y plutôt que nouvelle. C’est parce que vous l’envelopperiez avec quelque chose comme mymalloc () et que vous utiliseriez ensuite des fonctions dépendantes de l’architecture, telles que celles qui implémentent l’alignement approprié pour éviter les erreurs de cache et qui effectuent d’autres tâches astucieuses fournies par le fabricant du matériel, telles que IBM (Bluegene) ou Intel (MIC). Toutes ces routines d’allocation optimisées ont le cadre type Malloc.

1
Joel Giedt