Должен ли я включить stddef.h или cstddef для size_t - PullRequest
24 голосов
/ 22 февраля 2011

Когда я хочу использовать size_t в C ++, я должен включить <stddef.h> или <cstddef>? Я слышал, как несколько человек говорили, что <cstddef> была плохой идеей, и ее следует осудить. Почему это так?

Ответы [ 5 ]

40 голосов
/ 22 февраля 2011

stddef.h - заголовок C. Имя size_t находится в глобальном пространстве имен в нем. <cstddef>, с другой стороны, является заголовком C ++, который оборачивает имена C в пространство имен std, что, естественно, является подходом C ++, поэтому, если вы включите <cstddef> и компилятор будет совместимым, вам придется использовать std::size_t , Очевидно, что в C ++ подход C ++ более уместен. НТН

Редактировать: Технически, заголовок C тоже может содержать имена в пространстве имен std. Но C-заголовки (те, которые заканчиваются на .h) также вводят имена в глобальное пространство имен (таким образом, загрязняя его) с помощью деклараций использования.

13 голосов
/ 22 февраля 2011

Я предпочитаю #include <stddef.h>.

Некоторые имена в заголовках C могут быть макросами, но набор отличается от правил C.В C EXIT_FAILURE, isdigit(), getc() ao - макросы.Вы знаете, какие макросы в C ++ являются макросами?

Во-вторых, для заголовка <cfoo> требуется только пара стандартных заголовков C, а для заголовков Posix - нет.Знаете ли вы, какие заголовки являются стандартными, а какие предоставляются только вашим компилятором?

В-третьих, при использовании заголовков из сторонней библиотеки C вы получите #include <stddef.h>, и я предпочитаю не делать этого.mix <stddef.h> и <cstddef>.

В-четвертых, в текущем проекте нового стандарта C ++ сказано, что <cstdlib> разрешено выгружать символы в глобальное пространство имен (поскольку, по-видимому, многие компиляторы уже делают это в настоящее время)поэтому использование #include <cstdlib> не является гарантией того, что глобальное пространство имен будет незагрязнено в будущем.Поэтому я бы посоветовал, что при написании переносимого кода вы должны предполагать, что это повлияет на глобальное пространство имен (даже если это сейчас не разрешено).Поскольку, похоже, это знают только несколько экспертов (см. Обсуждение в комментариях здесь), лучше использовать <stddef.h>, поскольку даже начинающий программист на C ++ поймет, что он загрязняет глобальное пространство имен.

11 голосов
/ 22 февраля 2011

<stddef.h> официально является устаревшей частью C ++ (вместе с остальной частью Приложения D к стандарту C ++). Все они являются (не осуждаемыми) частями стандарта C, поэтому даже если они устарели в C ++, они практически наверняка останутся доступными практически до бесконечности.

Многие функции, которые не устарели , почти наверняка исчезнут первыми - export уже ушел из текущего проекта C ++ 0x, и, если бы мне пришлось угадывать, я ' Я бы сказал, что спецификации исключений были гораздо более вероятными, чем Приложение D. Когда / если эти заголовки действительно устареют, это, вероятно, будет из зрелой версии предложения модулей Дэвида Вандервурда, которое может легко отобразить все заголовки устарели.

В то же время значительное количество компиляторов (особенно старых) не реализуют заголовки <c*> точно так, как предписывает стандарт. Если вы хотите / должны написать код, который работает с ними, вы получите немало пользы, используя заголовки <*.h> вместо заголовков <c*>.

В конечном счете, я думаю, что заголовки <c*> были решением в поисках проблемы. Стандарт C требует, чтобы эти заголовки только определяли имена, которые требуются - вообще никаких других, кроме имен, которые зарезервированы, например, с начальным подчеркиванием, за которым следует другое подчеркивание или заглавная буква. Зарезервированные имена (и некоторые другие) также зарезервированы в C ++, поэтому в любом случае они не могут конфликтовать с чем-либо в переносимом коде. Таким образом, все заголовки <c*>, которые вы покупаете, - это возможность определить имя в глобальном пространстве имен, которое вступает в противоречие с существующим именем в стандартной библиотеке языка C. Это настолько впечатляюще ужасная идея, что даже не стоит задумываться над этим, поэтому с практической точки зрения вы ничего не получили.

Редактировать: Даже эта бесполезная возможность работала с небольшим количеством реальных компиляторов, так что текущие проекты улучшающего C ++ 0x разрешают заголовкам <c*> загрязнять глобальное пространство имен в любом случае, так что даже теоретическое преимущество исчезло .

2 голосов
/ 22 февраля 2011

Оба в стандарте и, AFAIK, там надолго.

Форма cXXX всегда вводит имена в пространствах имен std, форма XXX.h всегда вводит имена в глобальном пространстве имен. Оба могут также помещать имена в другое пространство имен (по крайней мере, в C ++ 0X, это не было ранее. Так как это ограничение делает невозможным создание библиотеки C ++ из библиотеки C, которой вы не управляете, ограничение было снято. g ++ страдает от этой проблемы, по крайней мере, для целей без glibc).

Для традиционных заголовков Unix во всех реализациях я тестировал форму XXX.h, включающую дополнительный идентификатор Unix, если у вас есть необходимые макросы функций, определенные ранее. Поведение для формы cXXX было несовместимым между реализациями. Поэтому на практике я использую XXX.h, так как мне часто нужны эти объявления.

0 голосов
/ 22 февраля 2011

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

...