web-dev-qa-db-fra.com

"Std :: size_t" a-t-il un sens en C ++?

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 );
}
58
jwfearn

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++.

129

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.

41
Don Wakefield

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.

13
fizzer
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é.

4
mloskot

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.

4
ypnos

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.

2
Brian R. Bondy

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; 
 
} 
2
Martin

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.

2
Michael S