Имеет ли смысл std :: size_t в C ++? - PullRequest
58 голосов
/ 26 октября 2008

В некотором коде, который я унаследовал, я часто вижу size_t с квалификатором пространства имен std. Например:

std::size_t n = sizeof( long );

Конечно, он компилируется и работает нормально. Но это кажется плохой практикой для меня (возможно, перенесено из C?).

Не правда ли, что size_t встроен в C ++ и, следовательно, в глобальное пространство имен? Нужно ли включать заголовочный файл для использования size_t в C ++?

Другой способ задать этот вопрос: можно ли ожидать, что следующая программа (с без вкл.) Будет компилировать на всех компиляторах C ++?

size_t foo()
{
    return sizeof( long );
}

Ответы [ 8 ]

129 голосов
/ 12 ноября 2008

Похоже, что среди стека переполнения стека путаница в отношении этого

::size_t определено в заголовке обратной совместимости stddef.h. Это было частью ANSI/ISO C и ISO C++ с самого их начала. Каждая реализация C ++ должна поставляться с stddef.h (совместимость) и cstddef, где только последняя определяет std::size_t и необязательно ::size_t. См. Приложение D к стандарту C ++.

41 голосов
/ 26 октября 2008

Раздел 17.4.1.2 стандарта C ++, пункт 4, гласит:

"Однако в стандартной библиотеке C ++ объявления и определения (за исключением имен, которые определены как макросы в C) находятся в пределах области имен (3.3.5) пространства имен std."

Сюда входят элементы, найденные в заголовках шаблона cname , включая cstddef , который определяет size_t.

Так что std :: size_t на самом деле правильный.

13 голосов
/ 26 октября 2008

Вы можете получить size_t в глобальном пространстве имен, включив, например, <stddef.h> вместо <cstddef>. Я не вижу никакой очевидной выгоды, и эта функция устарела.

4 голосов
/ 06 августа 2009
std::size_t n = sizeof( long );

На самом деле, вы не спросили, что конкретно является плохой практикой в ​​вышеизложенном. Использование size_t, квалификация с пространством имен std, ...

Как сказано в стандарте C ++ (18.1), size_t - это тип, определенный в стандартном заголовке. Я бы предложил отбросить любые мысли и впечатления о возможном наследовании языка Си. C ++ - это отдельный и другой язык, и его лучше рассматривать как таковой. Он имеет свою собственную стандартную библиотеку, и все элементы стандартной библиотеки C ++ определены в пространстве имен std. Тем не менее, можно использовать элементы стандартной библиотеки C в программе C ++.

Я бы посчитал, что это грязный хак. Стандарт C ++ гласит, что содержимое заголовков такое же или основано на соответствующих заголовках из стандартной библиотеки C, но в ряде случаев были применены изменения. Другими словами, это не прямое копирование и вставка заголовков C в заголовки C ++.

size_t не является встроенным типом в C ++. Это тип, определенный для указания того, какой тип целочисленного типа используется в качестве возвращаемого типа оператора sizeof (), поскольку фактический тип возвращаемого значения sizeof () определяется реализацией, поэтому стандарт C ++ объединяет путем определения size_t.

будет следующая программа (без включает в себя) ожидать компиляции на все компиляторы C ++?

size_t foo()
{
    return sizeof( long );
}

Стандарт C ++ гласит (1.4):

Имена, определенные в библиотеке, имеют область имен (7.3). Модуль перевода C ++ (2.1) получает доступ к этим именам, включая соответствующий стандартный заголовок библиотеки (16.2).

size_t - это имя, определенное в пространстве имен std, поэтому каждая программа, использующая это имя, должна включать соответствующий заголовок, в этом случае.

Далее в главе 3.7.3 говорится:

Однако ссылки на std, std :: bad_alloc и std :: size_t являются некорректными, если имя не было объявлено путем включения соответствующего заголовка.

Принимая во внимание, что программа, использующая size_t, но не включающая заголовок, некорректна.

4 голосов
/ 26 октября 2008

size_t не встроен в C ++. И это не определено по умолчанию. Этот не компилируется с GCC:

int main(int argc, char** argv) {
size_t size;
}

Тем не менее size_t является частью POSIX, и если вы используете только базовые вещи, такие как <cstdlib>, вы, вероятно, в конечном итоге определите его.

Вы можете утверждать, что std :: size_t является эквивалентом size_t в C ++. Как отметил Брайан, std :: используется как пространство имен, чтобы избежать установки глобальных переменных, которые не всем подходят. Это так же, как std :: string, который также может быть определен в корневом пространстве имен.

2 голосов
/ 12 мая 2009

Я думаю, что разъяснения достаточно ясны. std::size_t имеет смысл в C ++, а ::size_t имеет (по крайней мере) смысл в C.

Однако вопрос остается. А именно, можно ли предположить, что ::size_t и std::size_t совместимы?

С точки зрения чистой безопасности типов они не обязательно идентичны, если только где-то не определено, что они должны быть идентичны.

Я думаю, что многие используют что-то а-ля:

----
// 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 ) 
{
  ...
}

Так что в заголовке вы определенно используете ::size_t, а в исходном файле вы будете использовать std::size_t. Так что они должны быть совместимы, верно? В противном случае вы получите ошибку компилятора.

/ Майкл С.

2 голосов
/ 16 апреля 2009

Заголовки компилятора GNU содержат что-то вроде

typedef long int __PTRDIFF_TYPE__;
typedef unsigned long int __SIZE_TYPE__;

Тогда stddef.h содержит что-то вроде

typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;

И, наконец, файл cstddef содержит что-то вроде

#include <stddef.h>

namespace std {

  using ::ptrdiff_t;
  using ::size_t;

}

Я думаю, это должно прояснить это. Пока вы включаете , вы можете использовать size_t или std :: size_t, потому что size_t был определен по типу вне пространства имен std и затем был включен. Эффективно у вас есть

typedef long int ptrdiff_t;
typedef unsigned long int size_t;

namespace std {

  using ::ptrdiff_t;
  using ::size_t;

}
2 голосов
/ 26 октября 2008

Иногда другие библиотеки определяют свои собственные size_t. Например буст. std :: size_t указывает, что вы определенно хотите стандарт C ++.

size_t является стандартным типом c ++ и определяется в пространстве имен std.

...