Sans nom/anonyme espaces de noms vs statique fonctions
Une fonction de C++ est la possibilité de créer sans nom (anonyme) des espaces de noms, comme suit:
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 dans de l'extérieur. Mais ces espaces de noms sans nom sont accessibles dans le fichier, elles sont créées, comme si vous aviez un implicite à l'aide de la clause d'eux.
Ma question est, pourquoi et quand cela serait-il préférable à l'utilisation des fonctions statiques? Ou sont-ils essentiellement deux façons de faire exactement la même chose?
- En C++11 l'utilisation de
static
dans ce contexte a été undeprecated; bien que sans nom d'espace de noms est une alternative supérieure auxstatic
, la les cas où il échoue lorsquestatic
vient à la rescousse.
Vous devez vous connecter pour publier un commentaire.
Le C++ Standard, lit dans la section 7.3.1.1 sans nom les espaces de noms, paragraphe 2:Statique s'applique uniquement aux noms des objets, des fonctions et des syndicats, de ne pas les déclarations de type.
Edit:
La décision à rendre caduque cette utilisation du mot-clé static (affecter la visibilité d'une déclaration de variable dans une unité de traduction) a été inversé (ref). Dans ce cas, à l'aide d'un statique ou sans nom d'espace de noms sont de retour à être essentiellement deux façons de faire exactement la même chose. Pour plus de détails, veuillez voir cette DONC, la question.
Sans nom les espaces de noms ont encore l'avantage de vous permettre de définir la traduction-unité-types locaux. Veuillez voir cette DONC, la question pour plus de détails.
De crédit va à Mike Percy pour avoir porté à mon attention.
namespace
s ont implicitement une liaison interne, donc il devrait y avoir aucune différence. Toutes les questions qui pourraient déjà avoir surgi de la mauvaise formulation a été résolue par la prise de cette exigence dans C++11.Mettre dans un espace de noms anonymes vous évite de violer le Une Définition De La Règle, vous permettant de ne jamais vous soucier de nommage de vos méthodes d'assistance le même que toute autre méthode, vous pouvez créer un lien dans.
Et, comme l'a souligné luc, anonyme les espaces de noms sont privilégiées par la norme sur les membres statiques.
Il y a un cas limite où statique a un effet surprenant(au moins c'était pour moi). Le C++03 Standard unis dans 14.6.4.2/1:
Le code ci-dessous va appeler
foo(void*)
et pasfoo(S const &)
comme vous vous en doutez.En soi, ce n'est probablement pas un gros problème, mais elle met en évidence que, pour un entièrement conforme compilateur C++ (c'est à dire celui avec le soutien de
export
) lestatic
mot clé sera toujours avoir une fonctionnalité qui n'est pas disponible de toute autre manière.La seule façon de s'assurer que la fonction de notre sans nom d'espace de noms ne seront pas trouvés dans les modèles à l'aide de l'ADL est de rendre
static
.Mise à jour pour le C++ Moderne
Que de C++ 11, les membres d'un sans nom d'espace de noms ont une liaison interne implicitement (3.5/4):
Mais en même temps, 14.6.4.2/1 a été mis à jour pour supprimer la mention de la liaison (cette prise de C++ 14):
Le résultat c'est que cette différence entre statique et sans nom d'espace de noms des membres n'existe plus.
NS::S
de travail, n'est-ce pasS
besoin de ne pas être à l'intérieur denamespace {}
?NS::S
. Si vous êtes intéressés, 10.3.1.1 dans N4687 décrit la sémantique pour sans nom d'espace de noms et 6.4.3.2/2 décrit la recherche pour les noms qualifiés.J'ai récemment commencé à remplacer des mots-clés statiques avec anonyme des espaces de noms dans mon code, mais a immédiatement couru dans un problème où les variables dans l'espace de noms n'étaient plus disponibles pour l'inspection dans mon débogueur. J'ai été en utilisant VC60, donc je ne sais pas si c'est un non-problème avec d'autres débogueurs. Ma solution a été de définir un "module" espace de noms, où je lui ai donné le nom de mon fichier cpp.
Par exemple, dans mon XmlUtil.cpp fichier, je définir un espace de noms XmlUtil_I { ... } pour l'ensemble de mon module de variables et de fonctions. De cette façon, je peux appliquer le XmlUtil_I:: qualification dans le débogueur pour accéder aux variables. Dans ce cas, le '_I' distingue à partir d'un espace de noms tels que XmlUtil que je souhaiterez peut-être utiliser ailleurs.
Je suppose un inconvénient potentiel de cette approche par rapport à une véritable anonyme, c'est que quelqu'un pourrait violer le désiré statique de la portée en utilisant l'espace de noms qualifier dans d'autres modules. Je ne sais pas si c'est une préoccupation majeure si.
#if DEBUG namespace BlahBlah_private { #else namespace { #endif
, de sorte que le module "espace de noms" n'est présent que dans les versions de débogage et de vrai anonyme de l'espace de noms est utilisé autrement. Ce serait bien si les débogueurs a donné une belle façon de gérer cela. Doxygen devient confus par elle aussi.Utilisation du mot-clé static pour que le but soit obsolète par le C++98 standard. Le problème de l'électricité statique, c'est qu'il ne s'applique pas à la définition de type. C'est aussi une surcharge du mot-clé utilisé de différentes manières dans différents contextes, afin sans nom les espaces de noms de simplifier un peu les choses.
Par expérience, je vais prendre note que bien que c'est le C++ moyen de mettre autrefois-statique des fonctions dans l'espace de noms anonymes, les compilateurs plus âgés peuvent parfois avoir des problèmes avec cela. Je travaille actuellement avec un peu de compilateurs pour nos plateformes cibles, et les plus modernes de Linux compilateur est bien avec la mise en place des fonctions dans l'espace de noms anonymes.
Mais un vieux compilateur fonctionnant sous Solaris, que nous sommes en mer jusqu'à un quelconque avenir libération, parfois, de l'accepter, et d'autres fois drapeau comme une erreur. L'erreur n'est pas ce qui m'inquiète, c'est ce qu'il pourrait faire quand il accepte il. Donc, jusqu'à ce que nous allons moderne travers le conseil d'administration, nous sommes toujours à l'aide de statique (généralement de la classe d'étendue) des fonctions où l'on préfère l'anonymat de l'espace de noms.
En plus si on utilise le mot-clé static sur une variable comme dans cet exemple:
Il ne serait pas vu dans le fichier de mappage
Un compilateur spécifique différence entre anonymes espaces de noms et les fonctions statiques peut être vu de compiler le code suivant.
La compilation de ce code avec VS 2017 (en précisant le niveau 4 indicateur d'avertissement /W4 pour permettre avertissement C4505: non référencé à la fonction locale a été supprimé) et gcc 4.9 avec l'-Wunused-fonction ou -Mur drapeau indique que VS 2017 sera seulement de produire un avertissement pour le solde non utilisé fonction statique. gcc 4.9 et supérieur, ainsi que clang 3.3 et plus, permettra de produire des avertissements pour les non référencé à la fonction dans l'espace de noms et aussi un avertissement pour le solde non utilisé fonction statique.
Démo en Live de gcc 4.9 et MSVC 2017
Après avoir appris de cette fonction seulement maintenant alors que la lecture de votre question, je ne peux que spéculer. Ce qui semble fournir plusieurs avantages par rapport à un fichier de niveau statique de la variable:
Je serais intéressé à en apprendre si quelqu'un a utilisé anonyme espaces de noms dans le code réel.
Personnellement, je préfère des fonctions statiques sur nameless espaces de noms pour les raisons suivantes:
il est évident et clair de définition de la fonction du seul qu'il est privé de l'unité de traduction, où il est compilé. Avec namesless espace de noms que vous pourriez avoir besoin de faire défiler et de recherche pour voir si une fonction est dans un espace de noms.
fonctions dans les espaces de noms peuvent être traités comme des extern par certains (les plus âgés) des compilateurs. Dans VS2017 ils sont encore extern. Pour cette raison, même si une fonction est sans nom d'espace de noms, vous pouvez toujours marquer statique.
statique fonctions se comportent de manière très similaire en C ou en C++, alors que nameless les espaces de noms sont évidemment C++ seulement. nameless espaces de noms aussi ajouter un niveau supplémentaire si l'indentation et je n'aime pas ça 🙂
Donc, je suis heureux de voir que l'utilisation de la statique pour les fonctions n'est pas déconseillé plus.
static
mot-clé s'applique effectivement liaison locale à une fonction. Aussi, sûrement un fou furieux serait effectivement ajouter de l'indentation pour les espaces de noms?