Une caractéristique de C ++ est la possibilité de créer des espaces de noms sans nom (anonymes), comme ceci:
namespace {
int cannotAccessOutsideThisFile() { ... }
} // namespace
On pourrait penser qu'une telle fonctionnalité serait inutile - puisque vous ne pouvez pas spécifier le nom de l'espace de noms, il est impossible d'accéder à quoi que ce soit à l'intérieur de l'extérieur. Mais ces espaces de noms sans nom sont accessibles dans le fichier dans lequel ils sont créés, comme si vous y aviez une clause using implicite.
Ma question est: pourquoi ou quand est-ce préférable à l'utilisation de fonctions statiques? Ou s'agit-il essentiellement de deux façons de faire exactement la même chose?
c++
namespaces
Geek en chef
la source
la source
static
dans ce contexte n'était pas obsolète ; bien que l' espace de noms sans nom soit une alternative supérieure àstatic
, il y a des cas où il échoue quandstatic
vient à la rescousse .Réponses:
La norme C ++ lit à la section 7.3.1.1 Espaces de noms sans nom, paragraphe 2:Statique s'applique uniquement aux noms d'objets, de fonctions et d'unions anonymes, pas aux déclarations de type.
Éditer:
La décision de déprécier cette utilisation du mot-clé statique (affecter la visibilité d'une déclaration de variable dans une unité de traduction) a été inversée ( ref ). Dans ce cas, l'utilisation d'un espace de noms statique ou sans nom redevient essentiellement deux façons de faire exactement la même chose. Pour plus de discussion, veuillez consulter cette question SO.
Les espaces de noms sans nom ont toujours l'avantage de vous permettre de définir des types d'unités de traduction locales. Veuillez consulter cette question SO pour plus de détails.
Nous remercions Mike Percy d' avoir porté cela à mon attention.
la source
namespace
s sans nom ont implicitement un lien interne, donc il ne devrait pas y avoir de différence. Tous les problèmes qui pouvaient survenir auparavant à cause d'une mauvaise formulation ont été résolus en faisant de cette exigence en C ++ 11.Le fait de placer des méthodes dans un espace de noms anonyme vous empêche de violer accidentellement la règle de définition unique , ce qui vous permet de ne jamais vous soucier de nommer vos méthodes d'assistance de la même manière qu'une autre méthode à laquelle vous pouvez vous connecter.
Et, comme l'a souligné luke, les espaces de noms anonymes sont préférés par la norme aux membres statiques.
la source
Il y a un cas de bord où l'électricité statique a un effet surprenant (du moins c'était pour moi). La norme C ++ 03 stipule dans 14.6.4.2/1:
Le code ci-dessous appellera
foo(void*)
et pasfoo(S const &)
comme vous pourriez vous y attendre.En soi, ce n'est probablement pas si grave, mais cela met en évidence que pour un compilateur C ++ entièrement conforme (c'est-à-dire avec un support pour
export
), lestatic
mot - clé aura toujours des fonctionnalités qui ne sont pas disponibles autrement.La seule façon de s'assurer que la fonction dans notre espace de noms sans nom ne sera pas trouvée dans les modèles utilisant ADL est de la créer
static
.Mise à jour pour C ++ moderne
Depuis C ++ '11, les membres d'un espace de noms sans nom ont implicitement une liaison interne (3.5 / 4):
Mais en même temps, 14.6.4.2/1 a été mis à jour pour supprimer la mention de liaison (cela provient de C ++ '14):
Le résultat est que cette différence particulière entre les membres d'espace de noms statiques et non nommés n'existe plus.
la source
NS::S
travailler, n'a pasS
besoin de ne pas être à l'intérieurnamespace {}
?J'ai récemment commencé à remplacer des mots clés statiques par des espaces de noms anonymes dans mon code, mais j'ai immédiatement rencontré un problème où les variables de l'espace de noms n'étaient plus disponibles pour inspection dans mon débogueur. J'utilisais VC60, donc je ne sais pas si ce n'est pas un problème avec d'autres débogueurs. Ma solution de contournement consistait à définir un espace de noms «module», où je lui ai donné le nom de mon fichier cpp.
Par exemple, dans mon fichier XmlUtil.cpp, je définis un espace
XmlUtil_I { ... }
de noms pour toutes mes variables et fonctions de module. De cette façon, je peux appliquer laXmlUtil_I::
qualification dans le débogueur pour accéder aux variables. Dans ce cas, le le_I
distingue d'un espace de noms public tel queXmlUtil
celui que je souhaite utiliser ailleurs.Je suppose qu'un inconvénient potentiel de cette approche par rapport à une approche vraiment anonyme est que quelqu'un pourrait violer la portée statique souhaitée en utilisant le qualificateur d'espace de noms dans d'autres modules. Je ne sais pas si c'est une préoccupation majeure.
la source
#if DEBUG namespace BlahBlah_private { #else namespace { #endif
, donc "l'espace de noms du module" n'est présent que dans les versions de débogage et le véritable espace de noms anonyme est utilisé autrement. Ce serait bien si les débogueurs donnaient une bonne façon de gérer cela. L'oxygène se confond également avec lui.L'utilisation d'un mot clé statique à cet effet est déconseillée par la norme C ++ 98. Le problème avec statique est qu'il ne s'applique pas à la définition de type. C'est également un mot clé surchargé utilisé de différentes manières dans différents contextes, donc les espaces de noms sans nom simplifient un peu les choses.
la source
Par expérience, je noterai que même s'il s'agit du moyen C ++ de placer des fonctions anciennement statiques dans l'espace de noms anonyme, les anciens compilateurs peuvent parfois avoir des problèmes avec cela. Je travaille actuellement avec quelques compilateurs pour nos plates-formes cibles, et le compilateur Linux plus moderne est très bien avec le placement de fonctions dans l'espace de noms anonyme.
Mais un ancien compilateur fonctionnant sur Solaris, auquel nous sommes mariés jusqu'à une version future non spécifiée, l'acceptera parfois, et d'autres fois le signalera comme une erreur. L'erreur n'est pas ce qui m'inquiète, c'est ce qu'elle pourrait faire lorsqu'elle l' accepte . Donc, jusqu'à ce que nous passions à la modernité, nous utilisons toujours des fonctions statiques (généralement à portée de classe) où nous préférerions l'espace de noms anonyme.
la source
De plus si l'on utilise un mot-clé statique sur une variable comme cet exemple:
Il ne serait pas visible dans le fichier de mappage
la source
Une différence spécifique au compilateur entre les espaces de noms anonymes et les fonctions statiques peut être observée lors de la compilation du code suivant.
La compilation de ce code avec VS 2017 (en spécifiant l'indicateur d'avertissement de niveau 4 / W4 pour activer l' avertissement C4505: la fonction locale non référencée a été supprimée ) et gcc 4.9 avec l'indicateur -Wunused-function ou -Wall indique que VS 2017 ne produira qu'un avertissement pour la fonction statique inutilisée. gcc 4.9 et supérieur, ainsi que clang 3.3 et supérieur, produiront des avertissements pour la fonction non référencée dans l'espace de noms et également un avertissement pour la fonction statique inutilisée.
Démo en direct de gcc 4.9 et MSVC 2017
la source
Personnellement, je préfère les fonctions statiques aux espaces de noms sans nom pour les raisons suivantes:
Il est évident et clair à partir de la seule définition de fonction qu'elle est privée à l'unité de traduction où elle est compilée. Avec un espace de noms sans nom, vous devrez peut-être faire défiler et rechercher pour voir si une fonction se trouve dans un espace de noms.
Les fonctions dans les espaces de noms peuvent être traitées comme externes par certains (plus anciens) compilateurs. Dans VS2017, ils sont toujours externes. Pour cette raison, même si une fonction se trouve dans un espace de noms sans nom, vous pouvez toujours vouloir les marquer comme statiques.
Les fonctions statiques se comportent de manière très similaire en C ou C ++, tandis que les espaces de noms sans nom sont évidemment C ++ uniquement. les espaces de noms sans nom ajoutent également un niveau supplémentaire dans l'indentation et je n'aime pas ça :)
Donc, je suis heureux de voir que l'utilisation de static pour les fonctions n'est plus obsolète .
la source
static
mot - clé applique réellement le lien local à une fonction. De plus, seul un fou délirant ajouterait certainement une indentation pour les espaces de noms?Ayant appris cette fonctionnalité tout à l'heure en lisant votre question, je ne peux que spéculer. Cela semble offrir plusieurs avantages par rapport à une variable statique au niveau du fichier:
Je serais intéressé à savoir si quelqu'un a utilisé des espaces de noms anonymes dans du vrai code.
la source
La différence est le nom de l'identifiant modifié (
_ZN12_GLOBAL__N_11bE
vs_ZL1b
, ce qui n'a pas vraiment d'importance, mais les deux sont assemblés en symboles locaux dans la table des symboles (absence de.global
directive asm).Quant à un espace de noms anonyme imbriqué:
Tous les espaces de noms anonymes de 1er niveau dans l'unité de traduction sont combinés les uns avec les autres, Tous les espaces de noms anonymes imbriqués de 2e niveau dans l'unité de traduction sont combinés les uns avec les autres
Vous pouvez également avoir un espace de noms imbriqué (en ligne) dans un espace de noms anonyme
Vous pouvez également avoir des espaces de noms en ligne anonymes, mais pour autant que je sache,
inline
sur un espace de noms anonyme a un effet 0_ZL1b
:_Z
signifie qu'il s'agit d'un identifiant mutilé.L
signifie que c'est un symbole local à traversstatic
.1
est la longueur de l'identifiantb
, puis l'identifiantb
_ZN12_GLOBAL__N_11aE
_Z
signifie qu'il s'agit d'un identifiant mutilé.N
signifie qu'il s'agit d'un espace de noms12
est la longueur du nom d'espace de noms anonyme_GLOBAL__N_1
, puis le nom de l'espace de noms anonyme_GLOBAL__N_1
, puis1
la longueur de l'identifianta
,a
est l'identifianta
etE
ferme l'identifiant qui réside dans un espace de noms._ZN12_GLOBAL__N_11A1aE
est le même que ci-dessus, sauf qu'il y a un autre niveau d'espace de noms dedans1A
la source