Dans certains codes dont j'ai hérité, je vois une utilisation fréquente de size_t
avec le qualificatif d'espace de noms std
. Par exemple:
std::size_t n = sizeof( long );
Il compile et fonctionne bien, bien sûr. Mais cela me semble une mauvaise pratique (peut-être reportée de C?).
N'est-il pas vrai que size_t
est intégré dans C++ et donc dans l'espace de noms global? Un fichier d'en-tête est-il nécessaire pour utiliser size_t
en C++?
Une autre façon de poser cette question est la suivante: le programme suivant (avec non inclut) devrait-il compiler sur tous les compilateurs C++?
size_t foo()
{
return sizeof( long );
}
Il semble y avoir une confusion parmi la foule stackoverflow concernant cette
::size_t
est défini dans l'en-tête de compatibilité descendante stddef.h
. Cela fait partie de ANSI/ISO C
et ISO C++
depuis leur tout début. Chaque implémentation C++ doit être livrée avec stddef.h
(compatibilité) et cstddef
où seul ce dernier définit std::size_t
et pas nécessairement ::size_t
. Voir l'annexe D de la norme C++.
La section 17.4.1.2 de la norme C++, paragraphe 4, stipule que:
"Dans la bibliothèque standard C++, cependant, les déclarations et définitions (à l'exception des noms qui sont définis comme macros en C) sont dans la portée de l'espace de noms (3.3.5) de l'espace de noms std."
Cela inclut les éléments trouvés dans les en-têtes du modèle cname, y compris cstddef, qui définit size_t.
Donc std :: size_t est en fait correct.
Vous pouvez obtenir size_t
dans l'espace de noms global en incluant, par exemple, <stddef.h>
au lieu de <cstddef>
. Je ne vois aucun avantage évident et la fonctionnalité est obsolète.
std::size_t n = sizeof( long );
En fait, vous n'avez pas demandé ce qui semble être une mauvaise pratique dans ce qui précède. Utilisation de size_t, qualification avec espace de noms std, ...
Comme le dit la norme C++ (18.1), size_t est un type défini dans l'en-tête standard. Je suggère de laisser tomber toutes les pensées et impressions sur l'héritage possible du langage C. C++ est un langage séparé et différent et il vaut mieux le considérer comme tel. Il possède sa propre bibliothèque standard et tous les éléments de la bibliothèque standard C++ sont définis dans l'espace de noms std. Cependant, il est possible d'utiliser des éléments de la bibliothèque standard C dans le programme C++.
Je considérerais l'inclusion comme un hack sale. La norme C++ indique que le contenu des en-têtes est le même ou basé sur les en-têtes correspondants de la bibliothèque standard C, mais dans un certain nombre de cas, des modifications ont été appliquées. En d'autres termes, ce n'est pas un copier-coller direct des en-têtes C dans les en-têtes C++.
size_t n'est pas un type intégré en C++. Il s'agit d'un type défini pour spécifier le type de type intégral utilisé comme type de retour de l'opérateur sizeof (), car un type de retour réel de sizeof () est défini par l'implémentation, de sorte que le standard C++ s'unifie en définissant size_t.
le programme suivant (sans inclus) devrait-il être compilé sur tous les compilateurs C++?
size_t foo() { return sizeof( long ); }
La norme C++ dit (1.4):
Les noms définis dans la bibliothèque ont une portée d'espace de noms (7.3). Une unité de traduction C++ (2.1) obtient l'accès à ces noms en incluant l'en-tête de bibliothèque standard approprié (16.2).
Le size_t est un nom défini dans l'espace de noms std, donc chaque programme qui utilise ce nom doit inclure l'en-tête correspondant, dans ce cas.
Ensuite, le chapitre 3.7.3 dit:
Cependant, faire référence à std, std :: bad_alloc et std :: size_t est mal formé sauf si le nom a été déclaré en incluant l'en-tête approprié.
Étant donné que, le programme utilisant size_t mais sans inclure l'en-tête est mal formé.
size_t n'est pas intégré à C++. Et il n'est pas défini par défaut. Celui-ci ne compile pas avec GCC:
int main(int argc, char** argv) {
size_t size;
}
Cela dit, size_t fait partie de POSIX et si vous n'utilisez que des choses de base comme <cstdlib>
, vous finirez probablement par le faire définir.
Vous pourriez faire valoir que std :: size_t est l'équivalent C++ de size_t. Comme l'a souligné Brian, std :: est utilisé comme espace de noms pour éviter de définir des variables globales qui ne conviennent pas à tout le monde. C'est comme std :: string, qui aurait également pu être défini dans l'espace de noms racine.
Parfois, d'autres bibliothèques définiront leur propre taille_t. Par exemple, boost. std :: size_t spécifie que vous voulez définitivement le standard c ++.
size_t est un type standard c ++ et il est défini dans l'espace de noms std.
Les en-têtes du compilateur GNU contiennent quelque chose comme
typedef long int __PTRDIFF_TYPE __; typedef unsigned long int __SIZE_TYPE__;
Alors stddef.h contient quelque chose comme
typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __SIZE_TYPE__ size_t;
Et enfin, le fichier cstddef contient quelque chose comme
# inclut <stddef.h> espace de noms std { utilisant :: ptrdiff_t; utilisant :: size_t; }
Je pense que cela devrait être clair. Tant que vous incluez <cstddef>, vous pouvez utiliser size_t ou std :: size_t car size_t a été tapé en dehors de l'espace de noms std et a ensuite été inclus. Vous avez effectivement
typedef long int ptrdiff_t; typedef unsigned long int size_t; namespace std { using :: ptrdiff_t; utilisant :: size_t; }
Je pense que les clarifications sont suffisamment claires. Le std::size_t
est logique en C++ et ::size_t
faire (au moins) bon sens en C.
Cependant, une question demeure. À savoir s'il est sûr de supposer que ::size_t
et std::size_t
sont compatibles?
D'un point de vue purement sécurisé, ils ne sont pas nécessairement identiques à moins qu'il ne soit défini quelque part qu'ils doivent être identiques.
Je pense que beaucoup utilisent quelque chose à la mode:
----
// a.hpp
#include <string>
void Foo( const std::string & name, size_t value );
-----
// a.cpp
#include "a.hpp"
using namespace std;
void Foo( const string & name, size_t value )
{
...
}
Donc, dans l'en-tête, vous utilisez certainement le ::size_t
dans le fichier source, vous utiliserez std::size_t
. Ils doivent donc être compatibles, non? Sinon, vous obtiendrez une erreur de compilation.
/ Michael S.