Согласно cppreference.com size_t
определяется в нескольких заголовках, а именно
<cstddef>
<cstdio>
<cstring>
<ctime>
И, начиная с C ++ 11, также в
<cstdlib>
<cwchar>
Прежде всего мне интересно, почему это так. Разве это не противоречит принципу DRY ? Однако у меня вопрос:
Какой из вышеперечисленных заголовков я должен включить, чтобы использовать size_t
? Это вообще имеет значение?
<cstddef>
дляstd::size_t
std::size_t
, и OP не выступал за использование устаревших функций C, просто наблюдая за цитатой о том, что они разделяют typedef. Я сомневаюсь, что из-за этого кто-то, читающий эту ветку, будет введен в заблуждение относительно использования устаревших типов / функций, но если вы хотите быть уверены, что они этого не делают, тогда достаточно справедливо!Ответы:
Предполагая, что я хотел свести к минимуму импортированные функции и типы, я бы выбрал,
cstddef
поскольку он не объявляет никаких функций и объявляет только 6 типов. Другие фокусируются на определенных доменах (строки, время, ввод-вывод), которые могут не иметь для вас значения.Обратите внимание, что
cstddef
гарантирует только определениеstd::size_t
, то есть определениеsize_t
в пространстве именstd
, хотя он может предоставить это имя также в глобальном пространстве имен (фактически, обычномsize_t
).Напротив,
stddef.h
(который также является заголовком, доступным в C) гарантирует определениеsize_t
в глобальном пространстве имен, а также может предоставлятьstd::size_t
.источник
size_t
fromcstddef
такое же и всегда будет таким же, как и другие? Похоже, должен быть общий заголовочный файл с общими определениями вродеsize_t
...cstddef
.<cstddef>
или все они могут включать некоторый внутренний заголовок, который просто определяетsize_t
.csttddef
в ответе опечатка? Можетcstddef
имеется ввиду?Фактически, синопсис (включенный в стандарт C ++) нескольких заголовков специально включает,
size_t
а также дополнительные заголовки определяют типsize_t
(на основе стандарта C, поскольку<cX>
заголовки представляют собой просто<X.h>
заголовки ISO C с отмеченными изменениями, удалениеsize_t
которых не указано).Стандарт C ++ , однако, относится к
<cstddef>
для определенияstd::size_t
Поэтому и из-за того факта, что
<cstddef>
вводятся только типы, а не функции, я бы придерживался этого заголовка, чтобы сделать егоstd::size_t
доступным.Обратите внимание на несколько моментов:
Тип
std::size_t
можно получить с помощьюdecltype
без заголовкаЕсли вы планируете ввести ЬурейиЙ в коде в любом случае (то есть , потому что вы пишете контейнер и хотите , чтобы обеспечить
size_type
ЬурейиЙ) , вы можете использовать глобальныеsizeof
,sizeof...
илиalignof
оператор , чтобы определить ваш тип без включения каких - либо заголовков вообще , так как theose операторов возвращаютstd::size_t
в стандартного определения, и вы можете использоватьdecltype
на них:using size_type = decltype(alignof(char));
std::size_t
сам по себе не виден глобально, хотя функции сstd::size_t
аргументами видны.Неявно объявленные глобальные функции распределения и освобождения
void* operator new(std::size_t); void* operator new[](std::size_t); void operator delete(void*); void operator delete[](void*);
НЕ вводить
size_t
,std
илиstd::size_t
иПользователь не может переопределить,
std::size_t
хотя возможно иметь несколько определений типов, относящихся к одному и тому же типу в одном пространстве имен.Хотя наличие нескольких определений
size_t
внутриstd
вполне допустимо в соответствии с 7.1.3 / 3 , не разрешается добавлять какие-либо объявленияnamespace std
в соответствии с 17.6.4.2.1 / 1 :Добавление правильного typedef для
size_t
пространства имен не нарушает 7.1.3, но нарушает 17.6.4.2.1 и приводит к неопределенному поведению.Уточнение: постарайтесь не неверно истолковать 7.1.3 и не добавлять декларации или определения в
std
(за исключением нескольких случаев специализации шаблона, когда typedef не является специализацией шаблона). Расширениеnamespace std
источник
std
недопустимо, потому что дублирование typedef недопустимо. Я заявляю, что это незаконно, потому что вы просто не можете добавлять определения кnamespace std
- независимо от того, будут ли они законными.Все заголовочные файлы стандартной библиотеки имеют одинаковое определение; не имеет значения, какой из них вы включите в свой собственный код. На моем компьютере есть следующее объявление в формате
_stddef.h
. Этот файл включен в каждый указанный вами файл./* Define the size_t type in the std namespace if in C++ or globally if in C. If we're in C++, make the _SIZE_T macro expand to std::size_t */ #if !defined(_SIZE_T) && !defined(_SIZE_T_DEFINED) # define _SIZE_T_DEFINED #if defined(_WIN64) typedef unsigned __int64 size_t; #else typedef unsigned int size_t; #endif # if defined(__cplusplus) # define _SIZE_T std::size_t # else # define _SIZE_T size_t # endif #endif
источник
size_t
?size_t
. Вы можете определить его более переносимо какusing size_t = decltype( sizeof( 42 ) )
. Но в этом нет необходимости, так как<stddef.h>
он практически нулевой.Можно было обойтись без заголовка:
using size_t = decltype(sizeof(int)); using size_t = decltype(sizeof 1); // The shortest is my favourite. using size_t = decltype(sizeof "anything");
Это связано с тем, что стандарт C ++ требует:
Другими словами, стандарт требует:
static_assert(std::is_same<decltype(sizeof(int)), std::size_t>::value, "This never fails.");
Также обратите внимание, что это совершенно нормально сделать это
typedef
объявление в глобальном и вstd
пространстве имен, если оно соответствует всем другимtypedef
объявлениям того же typedef-name (при несоответствующих объявлениях выдается ошибка компилятора).Это потому что:
§7.1.3.1 typedef-name не вводит новый тип в отличие от объявления класса (9.1) или объявления enum.
§7.1.3.3 В заданной неклассовой области видимости
typedef
можно использовать спецификатор для переопределения имени любого типа, объявленного в этой области, чтобы ссылаться на тип, на который он уже ссылается.Скептикам, утверждающим, что это представляет собой добавление нового типа в пространство имен
std
, и такое действие явно запрещено стандартом, и это UB, и это все, что нужно; Я должен сказать, что такое отношение сводится к игнорированию и отрицанию более глубокого понимания основных проблем.Стандарт запрещает добавление новых деклараций и определений в пространство имен,
std
потому что таким образом пользователь может испортить стандартную библиотеку и оторвать себе всю ногу. Для стандартных писателей было легче позволить пользователю специализироваться на нескольких конкретных вещах и запретить делать что-либо еще для хорошей меры, чем запрещать все, что пользователь не должен делать, и рисковать пропустить что-то важное (и эту ногу). Они делали это в прошлом, когда требовали, чтобы ни один стандартный контейнер не создавался с неполным типом, тогда как на самом деле некоторые контейнеры вполне могли это сделать (см. «Стандартный библиотекарь: контейнеры неполных типов» Мэтью Х. Остерна ):Учитывая, что языковые правила должны
std::size_t
быть точнымиdecltype(sizeof(int))
, выполнениеnamespace std { using size_t = decltype(sizeof(int)); }
- одна из тех вещей, которые ничего не нарушают.До C ++ 11 не было
decltype
и, следовательно, не было возможности объявить типsizeof
результата в одном простом операторе без использования большого количества шаблонов.size_t
псевдонимы разных типов на разных целевых архитектурах, однако было бы не лучшим решением добавить новый встроенный тип только для результатаsizeof
, а стандартные встроенные определения типов отсутствуют. Следовательно, наиболее переносимым решением в то время было поместитьsize_t
псевдоним типа в какой-то определенный заголовок и задокументировать его.В C ++ 11 теперь есть способ записать это точное требование стандарта в виде одного простого объявления.
источник
size_t
!» Минутой позже Мэри сказала: «Боже мой! Есть 7 определенийsize_t
заголовков стандартных библиотек и заголовок проекта, который Том редактирует! Возможно, их больше в сторонних библиотеках!» xkcd.com/927size_t
, это не отвечает на настоящий вопрос OP: это как если бы я попросил заголовок, в которомFILE
объявлен, и вы бы предложили написать свой собственный.