web-dev-qa-db-fra.com

variables statiques vs non statiques dans un espace de noms

J'ai un espace de noms foo qui contient un entier bar, déclaré ainsi ...

foo.h:

namespace foo {
    int bar;
}

Maintenant, si j'inclus foo.h dans un seul fichier, cela fonctionne très bien. Mais un problème se pose lorsque j'inclus foo.h à partir de deux fichiers ou plus: je reçois une erreur de l'éditeur de liens. J'ai compris que si je déclarais bar comme static, je pourrais inclure foo.h dans plusieurs fichiers. Cela me semble étrange, car je ne savais pas que l'on pouvait déclarer une variable statique à l'intérieur d'un espace de noms. (Qu'est ce que ça veut dire?)

Pourquoi ça marche? Et plus important encore, pourquoi ne fonctionne pas cela fonctionne sansstatic? Que signifie static quand utilisé dans namespace?

34
Michael Dorst

Il existe plusieurs significations pour static dans différents contextes. Dans ce contexte particulier, cela signifie que la variable a un lien interne et que chaque unité de traduction qui inclut cet en-tête aura sa propre copie de la variable.

Notez que, même si cela supprime l'erreur de l'éditeur de liens, il conserve une variable foo::bar distincte pour chacun des fichiers objet générés (les modifications ne seront pas visibles entre différents fichiers objet).

Si vous souhaitez une seule variable, vous devez la déclarer en tant que extern dans l'en-tête et fournir une définition unique dans une unité de traduction.

Lorsque vous déclarez une variable en tant que static, cela signifie que son étendue est limitée à l'unité de traduction donnée uniquement. Sans static, la portée est globale.

Lorsque vous déclarez une variable sous la forme static dans un fichier .h (au sein ou sans namespace; peu importe) et que vous incluez ce fichier d'en-tête dans divers fichiers .cpp, la variable static devient localement étendue à chacun des fichiers .cpp.
Alors, chaque fichier .cpp contenant cet en-tête aura sa propre copie de cette variable.

Sans le mot clé static, le compilateur générera une seule copie de cette variable. Ainsi, dès que vous incluez le fichier d'en-tête dans plusieurs fichiers .cpp, l'éditeur de liens se plaindra de plusieurs définitions.

24
iammilind

Le problème est causé par plusieurs définitions de la variable. Les définitions dans différentes unités de traduction sont en conflit, tout comme plusieurs définitions de fonction non intégrées ne fonctionneraient pas.

Lorsque vous associez la variable à la variable, vous lui attribuez un lien interne, de sorte que chaque unité de traduction possède sa propre copie indépendante.

Ce que vous voulez probablement, en réalité, est de ne mettre que la déclaration dans un en-tête (en utilisant extern), puis de placer la définition dans un fichier d'implémentation.

4
bames53

Notez également que const int dans la portée (globale) de l'espace de noms (global) en C++ a static ajouté implicitement par défaut: Définir des variables constantes dans l'en-tête C++

Pour mieux comprendre ce qui se passe, faites une readelf sur les fichiers d'objet ELF intermédiaires de la compilation et vous verrez clairement si les symboles sont définis deux fois ou non. Voici un exemple détaillé: Que signifie "statique" en C?