При использовании заголовков C в C++, мы должны использовать функции из std:: или глобального пространства имен?

C - это не совсем подмножество C++. Таким образом, мы можем использовать большинство функций / заголовков C в C++, немного изменив имя (stdio.h в cstdio, stdlib.h в cstdlib).

Мой вопрос на самом деле является семантическим. В коде C++ (используя новейшую версию компилятора GCC) я могу вызвать printf("Hello world!); а также std::printf("Hello world!); и работает точно так же. И в ссылке, которую я использую, это также выглядит как std::printf("Hello world!);,

Мой вопрос, является ли это предпочтительным для использования std::printf(); в С ++? Есть ли разница?

9 ответов

Решение

Из стандарта C++11 (выделено мое):

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

  1. Для совместимости со стандартной библиотекой C...
  2. Каждый заголовок C, каждый из которых имеет имя формы name.h, ведет себя так, как будто каждое имя, помещенное в стандартное пространство имен библиотеки соответствующим заголовком cname, помещается в глобальную область пространства имен. Не определено, были ли эти имена сначала объявлены или определены в пределах области имен (3.3.6) пространства имен std, а затем введены в глобальную область имен с помощью явных объявлений using (7.3.3).
  3. Пример: заголовок <cstdlib> гарантированно обеспечивает свои объявления и определения в пространстве именstd, Он также может предоставлять эти имена в глобальном пространстве имен. Заголовок <stdlib.h> несомненно, обеспечивает те же объявления и определения в глобальном пространстве имен, как и в стандарте C. Он также может предоставлять эти имена в пространстве имен std,

Использование заголовков "name.h" не рекомендуется, они были определены как кандидаты на удаление из будущих версий.

Итак, я бы предложил включить заголовки "cname" и использовать объявления и определения из std Пространство имен.

Если по каким-либо причинам вам придется использовать заголовки "name.h" (это устарело, см. Выше), я бы предложил использовать объявления и определения из глобального пространства имен.

Другими словами: предпочитаю

#include <cstdio>

int main() {
    std::printf("Hello world\n");
}

над

#include <stdio.h>

int main() {
    printf("Hello world\n");
}

<cmeow> всегда обеспечивает ::std::purr и может или не может предоставить ::purr,

<meow.h> всегда обеспечивает ::purr и может или не может предоставить ::std::purr,

Используйте форму, которая гарантированно будет указана в заголовке, который вы включаете.

Нет, ты в порядке в любом случае.

Первоначально предполагалось, что <___.h> Заголовки будут версиями C, которые помещают все в глобальное пространство имен, а <c___> заголовки будут версиями C++-ified, которые помещают все в std Пространство имен.

На практике, однако, версии C++ также помещают все в глобальное пространство имен. И нет единого мнения, что использование std:: Версии "правильная вещь".

Так что, в основном, используйте то, что вы предпочитаете. Наиболее распространенным является, вероятно, использование стандартных функций библиотеки C в глобальном пространстве имен (printf вместо std::printf), но нет особых оснований считать одно "лучше" другого.

Из стандарта C++11:

Каждый заголовок C, каждый из которых имеет имя формы name.h, ведет себя так, как будто каждое имя, помещенное в стандартное пространство имен библиотеки соответствующим заголовком cname, помещается в глобальную область пространства имен. Не определено, были ли эти имена сначала объявлены или определены в пределах области имен (3.3.6) пространства имен std, а затем введены в глобальную область имен с помощью явных объявлений using (7.3.3).

Итак, если вы используете <cstdio>можете быть уверены, что printf будет в namespace stdи, следовательно, не в глобальном пространстве имен.
Использование глобального пространства имен создает конфликт имен. Это не C++ путь.

Поэтому я использую <cstdio> Заголовки и советую вам сделать это.

Из моей собственной практики: использовать std:: префиксы. В противном случае один день abs будет очень больно кусать вас, если вы используете плавающие точки.

Неквалифицированный abs относится к функции, определенной на int на некоторых платформах. На других это перегружено. тем не мение std::abs всегда перегружен для всех типов.

Единственная разница в том, что в std::printf() добавляя std:: Разрешение области действия Вы обезопасите себя от того, что кто-то напишет в будущем функцию с тем же именем, что приведет к конфликту пространства имен. Оба варианта использования приведут к абсолютно одинаковым вызовам API OS (вы можете проверить это в Linux, запустив strace your_program).

Я считаю очень маловероятным, чтобы кто-то назвал такую ​​функцию, как printf() это одна из наиболее часто используемых функций. Кроме того, в C++, iostreamпредпочтительнее звонков cstdio функции, такие как printf.

Используя только printf без std:: может генерировать некоторые конфликты имен и считается плохой практикой для многих разработчиков C++. Google ваш друг на этом, но вот несколько ссылок, надеюсь, это поможет

Почему "использование пространства имен std" считается плохой практикой? http://www.cplusplus.com/forum/beginner/61121/

В студии

Это версия C++ заголовка стандартной библиотеки C @c stdio.h, и его содержимое (в основном) совпадает с заголовком, но все содержится в пространстве имен @c std (за исключением имен, которые определены как макросы в С).

Так что это не должно иметь никакого значения.

Прежде всего, это широко известная функция в библиотеке C, и почти никто не хотел бы называть ее как .

Во-вторых, в заголовочном файле<cstdio>, оба вstdпространство имен и глобальное пространство имен. Так что написание префикса или нет работает одинаково.

На мой взгляд, если ваш код и используемая вами библиотека не содержат никаких других пространств имен. Просто используйте, по крайней мере, вы сэкономите свое время на наборе текста.std::. Или лучше использовать, чтобы избежать возможных конфликтов имен.std::printfбезопаснее.printfэто удобнее.

Другие вопросы по тегам