Должен ли я включить & lt; xxxx.h & gt; или & lt; cxxxx & gt; в программах на C ++?

  • Что я должен включить в программы на C ++, stdio.h или же cstdio? и почему?
  • Почему два заголовочных файла, которые обеспечивают одинаковую функциональность?
  • Что стандарт говорит об этом?
  • Как мне включить другие такие заголовки. Есть ли базовое правило, которому я должен следовать?

48

Решение

Рассмотрим следующие программы:

Образец 1:

#include<stdio.h>

int main()
{
printf("Hello World");
return 0;
}

Образец 2:

#include<cstdio>

int main()
{
printf("Hello World");
return 0;
}

Оба работают как положено. Так какое использование является более подходящим?
Ответ: Ни! Удивлены? Читать дальше.

Стандартная библиотека C ++ предоставляет все стандартные заголовки C для совместимости, в то время как C ++ как язык также предоставляет все эквивалентные заголовки. Как соглашение,

  • Никакие стандартные заголовки библиотеки C ++ (кроме включенных для совместимости с C) не имеют расширений файлов, и
  • Все эквиваленты C ++ заголовков C начинаются с cxxxxx,

Стандарт C ++ упоминает это под Приложение D (нормативное) Особенности совместимости:

Стандартное цитирование

§ 2 упоминает важный отличительный момент. Это правило, примененное к приведенным выше примерам, означает:

  • В том числе cstdio импортирует имена символов в пространстве имен std и возможно в глобальном пространстве имен.
  • В том числе stdio.h импортирует имена символов в глобальном пространстве имен и возможно в пространстве имен std.

Давайте применим это правило к нашим образцам кодов и измерим все за и против:

Образец 1:
Это приводит все символы из stdio.h в глобальное пространство имен. Преимущество состоит в том, что вы можете использовать символы без какой-либо квалификации, поскольку они импортируются в глобальное пространство имен. Недостатком является то, что вы в конечном итоге загрязняете глобальное пространство имен многими именами символов, которые вы, вероятно, никогда не будете использовать. Это может привести к конфликту имен символов. В C ++ всегда рассматривайте глобальное пространство имен как минное поле и по возможности избегайте его.

Образец 2:
Это очень плохая практика, потому что нет гарантии, что реализация поместит символы в глобальное пространство имен, стандарт просто не требует этого. Мы просто полагаемся на поведение одной конкретной реализации компилятора. Мы не можем и не должны предполагать, что все компиляторы будут делать это. Строго говоря, программа не одобрена стандартом, и это использование не переносимо во всех реализациях.

Так что такое правильное использование?

Правильное использование заключается в использовании cstdio и полностью квалифицировать имена символов или привести их в область видимости using декларации. Это гарантирует, что все символы, которые мы используем, присутствуют в std пространство имен, и мы не загрязняем глобальное пространство имен. Пример правильного использования:

Образец 3:

#include<cstdio>

using std::printf;

int main()
{
printf("Hello World");
return 0;
}

Обратите внимание, что директива using namespace std;, особенно в шапке, не очень хороший вариант и вы всегда должны использовать using деклараций.

Обратите внимание, что мы считаем stdio.h против cstdio здесь только пример использования, на практике это относится к все самый cxxxx а также xxxx.h заголовки, кроме нескольких как <math.h> а также <cmath>.

59

Другие решения

Поскольку этот пост немного устарел, я хотел бы поделиться следующим:


Глядя на код:

Using X.h   // Compatible with C language standard
---------------
#include <X.h>

int main() {
// Invoke X's corresponding function
return 0;
}

Using X    // Not compatible with C language standard
--------------
#include <X>

int main() {
// Invoke X's corresponding function
return 0;
}

Они оба компилируются и исполняются нормально!


Какой из них лучше в C ++?

относительно C ++ 11и C ++ 17спецификация:

С.5.1 (раздел из документа C ++ 17)
Модификации заголовков [diff.mods.to.headers]

  1. Для совместимости со стандартной библиотекой C стандартная библиотека C ++ предоставляет заголовки C, перечисленные в D.5, но их использование
    устарел в C ++.

  2. Для заголовков C нет заголовков C ++ <stdatomic.h>, <stdnoreturn.h>, а также <threads.h>и сами заголовки C
    часть С ++.

  3. Заголовки C ++ <ccomplex> (D.4.1) и <ctgmath> (D.4.4), а также их соответствующие заголовки C <complex.h> а также <tgmath.h>, не делайте
    содержат любой контент из стандартной библиотеки C и вместо
    просто включите другие заголовки из стандартной библиотеки C ++.


Д.5
Заголовки стандартной библиотеки C [depr.c.headers]
1. Для совместимости со стандартной библиотекой C стандартная библиотека C ++ предоставляет заголовки C, показанные в таблице 141.

введите описание изображения здесь

И то и другое C ++ 11 а также C ++ 17 Стандартные технические документы утверждают использование <X.h> остается для совместимости со стандартом C, хотя их использование рассматривается как осуждается.


относительно C ++ 20 стандартное предложение

Они рассматривают «Undeprecating» использование заголовков библиотеки C в C ++ 20. <X.h> выделены зеленым цветом. C ++ 11 и C ++ 17 устарели, на данный момент, заявлено как «слабая рекомендация» и «твик» для сохраненияЗаголовки стандартной библиотеки C (c.headers)«отображается ниже:

«Базовые заголовки библиотеки C являются важной функцией совместимости, и в ближайшее время никуда не денутся». (от Обзорный документ C ++ 20)


Стандарт D.5 C
заголовки библиотеки [depr.c.headers]

Слабая рекомендация: В дополнение к вышесказанному, также удалите
соответствующие заголовки C из стандарта C ++, так как у нас нет
соответствующий <stdatomic.h>, <stdnoreturn.h>, или же <threads.h>Заголовки.
Как и выше, но со следующими настройками:
20.5.5.2.1 Заголовки стандартной библиотеки C [c.headers]

Для совместимости со стандартной библиотекой C, стандартом C ++
библиотека предоставляет заголовки C, показанные в таблице 141. Таблица 141 — C
заголовки

 <assert.h>  <inttypes.h>   <signal.h>      <stdio.h>   <wchar.h>
<complex.h> <iso646.h>     <stdalign.h>    <stdlib.h>  <wctype.h>
<ctype.h>   <limits.h>     <stdarg.h>      <string.h>
<errno.h>   <locale.h>     <stdbool.h>     <tgmath.h>
<fenv.h>    <math.h>       <stddef.h>      <time.h>
<float.h>   <setjmp.h>     <stdint.h>      <uchar.h>

Заголовок <complex.h>
ведет себя так, как будто он просто включает в себя заголовок <complex>,
Заголовок <tgmath.h> ведет себя так, как будто он просто включает в себя заголовки <complex> а также <cmath>,


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

Ну, это похоже <X.h> не куда угодно. В конечном счете, вы можете использовать оба. Лично я бы решил, какой из них я буду использовать, чтобы ваш код обратная совместимость с кодом C или нет.

5