При использовании стандартных функций C в С++ требуется ли префикс "std::"?
При использовании стандартной функции C в С++ мы должны префикс каждой функции с помощью std::
?
например (имя файла: std.C
):
#include <cstdio>
int main() {
std::printf("hello\n");
printf("hello\n");
}
Этот файл можно скомпилировать с помощью:
g++ -Wall -Werror -std=c++11 std.C
без ошибок.
мои вопросы:
- Должны ли мы всегда размещать
std::
перед всеми стандартными функциями библиотеки C, когда они используются в С++?
- Какое основное различие между заголовочными файлами, такими как
<stdio.h>
и <cstdio>
?
Ответы
Ответ 1
Библиотека С++ содержит те же определения, что и язык C библиотека, организованная в той же структуре файлов заголовков, с следующие отличия:
- Каждый заголовочный файл имеет то же имя, что и версия на языке C, но с префиксом "
c
" и без расширения. Например, эквивалент С++ для файла заголовка языка C <stdlib.h>
есть <cstdlib>
. - Каждый элемент библиотеки определяется в пространстве имен
std
.
Тем не менее, для совместимости с C традиционные имена заголовков name.h
(например, stdlib.h
) также предоставляются те же определения в глобальном пространстве имен, хотя его использование устарело в С++.
(источник)
Часть std::
вызова std::printf()
является стандартным способом использования имен в стандартной библиотеке, поэтому я предлагаю использовать ее.
Ответ 2
Стандартная библиотека С++ включает в себя стандартную библиотеку C (с несколькими небольшими изменениями).
Каждый заголовок C с именем типа <foo.h>
имеет соответствующий заголовок С++ <cfoo>
. Например, заголовок С++ <cstdio>
соответствует заголовку C <stdio.h>
.
Цитирование стандарта ISO С++ 2011 года, 17.6.1.2 [заголовки], пункт 4:
Однако в стандартной библиотеке С++ объявления (кроме имена, которые определены как макросы в C) находятся в области пространства имен (3.3.6) пространства имен std
. Неизвестно, являются ли эти имена сначала объявляются в области глобального пространства имен, а затем вводится в пространство имен std
посредством явных использования-деклараций (7.3.3).
Таким образом, для #include <cstdio>
функция printf
определенно может называться std::printf
и необязательно может быть видна как printf
в глобальном пространстве имен. (Эта опция зависит от реализации, а не от программиста.)
Конечно, вы можете ссылаться на него как на printf
в рамках using namespace std
.
По-моему, это несчастливо; это похоже на удобство разработчиков, а не программистов. Можно с уверенностью предположить, что printf
объявляется только в пространстве имен std
. Если вы используете #include <cstdio>
, а затем обратитесь к printf
в глобальном пространстве имен, ваш код может компилироваться сегодня и не скомпилироваться в другой реализации.
И наоборот, как устаревшая функция, стандартная библиотека С++ также включает стандартные заголовки C с их исходными именами, например <stdio.h>
. Цитируя стандарт, раздел D.5 [des.c.header]:
Каждый заголовок C, каждый из которых имеет имя формы name.h
, ведет себя так, как если бы каждое имя помещалось в пространство имен стандартной библиотеки на соответствующий заголовок cname помещается в глобальное пространство имен объем. Не указано, объявлены ли эти имена сначала или определенных в пространстве пространства имен (3.3.6) пространства имен std
и затем вводятся в область глобального пространства имен с помощью явного Использование-декларации (7.3.3).
Таким образом, имя #include <stdio.h>
, имя printf
определенно отображается в глобальном пространстве имен и необязательно (опять же, это вариант реализации, а не ваш), видимый как std::printf
.
Ответ 3
- std - это пространство имен и с помощью :: (после std) вы явно используете функции пространства имен std. Теперь представьте, что вы создаете собственное пространство имен, а некоторые из созданных вами функций имеют то же имя, что и функции в пространстве имен std. Это может быть проблемой, но с помощью std:: func1 и YourNameSpace:: func1 вы предотвращаете эту проблему.
- Посмотрите здесь. Спасибо @karma_geek