"Std:: size_t" имеет смысл в С++?
В некотором коде, который я унаследовал, я часто использую size_t
с квалификатором пространства имен std
. Например:
std::size_t n = sizeof( long );
Он компилируется и работает нормально, конечно. Но мне кажется плохой практикой (возможно, перенесенной с C?).
Не правда ли, что size_t
встроен в С++ и, следовательно, в глобальное пространство имен? Должен ли заголовочный файл использовать size_t
в С++?
Другой способ задать этот вопрос: не ожидается ли компиляция следующей программы (без включения) для всех компиляторов С++?
size_t foo()
{
return sizeof( long );
}
Ответы
Ответ 1
Кажется, у толпы stackoverflow есть путаница относительно этого
::size_t
определяется в заголовке обратной совместимости stddef.h
. Он был частью ANSI/ISO C
и ISO C++
с самого начала. Каждая реализация С++ должна поставляться с stddef.h
(совместимостью) и cstddef
, где только последняя определяет std::size_t
и необязательно ::size_t
. См. Приложение D стандарта С++.
Ответ 2
В разделе 17.4.1.2 стандарта С++, параграф 4, указано, что:
"Однако в стандартной библиотеке С++ декларации и определения (за исключением имен, которые определены как макросы в C) находятся в области пространства имен (3.3.5) пространства имен std."
Это включает элементы, найденные в заголовках шаблона cname, включая cstddef, который определяет size_t.
Итак, std:: size_t на самом деле прав.
Ответ 3
Вы можете получить size_t
в глобальном пространстве имен, включив, например, <stddef.h>
вместо <cstddef>
. Я не вижу никакой очевидной выгоды, и функция устарела.
Ответ 4
size_t не встроен в С++. И он не определяется по умолчанию. Это не компилируется с помощью GCC:
int main(int argc, char** argv) {
size_t size;
}
Тем не менее, size_t является частью POSIX, и если вы используете только такие основные вещи, как <cstdlib>
, вы, скорее всего, закончите тем, что он определен.
Можно утверждать, что std:: size_t является эквивалентом С++ для size_t. Как отметил Брайан, std:: используется как пространство имен, чтобы избежать установки глобальных переменных, которые не подходят всем. Это просто как std::string, который также может быть определен в корневом пространстве имен.
Ответ 5
std::size_t n = sizeof( long );
Собственно, вы не спросили, что конкретно кажется плохой практикой в вышеупомянутом. Использование size_t, квалификация с пространством имен std,...
Как утверждает стандарт С++ (18.1), size_t - это тип, определенный в стандартном заголовке. Я предлагаю отказаться от любых мыслей и впечатлений о возможном наследовании с языка C. С++ - это отдельный и другой язык, и лучше рассмотреть его как таковой. Он имеет собственную стандартную библиотеку, и все элементы стандартной библиотеки С++ определены в пространстве имен std. Однако в С++ можно использовать элементы C Standard Library.
Я бы подумал о включении в качестве грязного взлома. В стандарте С++ указано, что содержимое заголовков одинаковое или основано на соответствующих заголовках из стандартной библиотеки C, но в ряде случаев были применены изменения. Другими словами, это не прямая копия и вставка заголовков C в заголовки С++.
size_t не является встроенным типом в С++. Это тип, определенный для указания того, какой тип интеграла используется как возвращаемый тип оператора sizeof(), поскольку фактический тип возвращаемого значения sizeof() определяется реализацией, поэтому стандарт С++ унифицируется путем определения size_t.
будет следующая программа (без включает в себя) все компиляторы С++?
size_t foo()
{
return sizeof( long );
}
В стандарте С++ говорится (1.4):
Имена, определенные в библиотеке, имеют область пространства имен (7.3). Модуль перевода С++ (2.1) получает доступ к этим именам, включая соответствующий стандартный заголовок библиотеки (16.2).
size_t - это имя, определенное в пространстве имен std, поэтому каждая программа, использующая это имя, должна включать соответствующий заголовок в этом случае.
Далее в главе 3.7.3 говорится:
Однако, ссылаясь на std, std:: bad_alloc и std:: size_t, плохо сформирован, если имя не было объявлено включением соответствующего заголовка.
Учитывая, что программа с использованием size_t, но не включая заголовок, плохо сформирована.
Ответ 6
Иногда другие библиотеки определяют свой собственный size_t. Например, повышение. std:: size_t указывает, что вам определенно нужен стандартный С++.
size_t является стандартным типом С++ и определяется в пространстве имен std.
Ответ 7
Я думаю, что разъяснения достаточно ясны. std::size_t
имеет смысл в С++ и ::size_t
сделать (по крайней мере) здравый смысл в C.
Однако вопрос остается. А именно, можно ли считать, что ::size_t
и std::size_t
совместимы?
С точки зрения чистого вида они не обязательно идентичны, если они не определены где-то, что они должны быть идентичными.
Я думаю, что многие используют что-то a la:
----
// 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 )
{
...
}
Итак, в заголовке вы defintely используете ::size_t
, а в исходном файле вы будете использовать std::size_t
. Значит, они должны быть совместимыми, верно? В противном случае вы получите ошибку компилятора.
/Майкл С.
Ответ 8
Заголовки компилятора 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;
}
Я думаю, что это должно быть ясно. Пока вы включаете <cstddef> вы можете использовать либо 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;
}