по С++: зачем нужен std:: если iostream уже включен?
новичок в программировании, пожалуйста объясните по возможности подробнее.
В одном и том же заголовочном файле может быть несколько пространств имен.
Тем более много пространств имен можно включить в код, если подключить много заголовочных файлов.
А в разных пространствах имен могут быть члены с одинаковыми именами.
Пространство имен указывают перед . чтобы не перепутать, и обратиться к cout или cin именно из пространства имен std, а не какого-то другого пространства имен из iostream или еще какого-то заголовочного файла, включенного через include.
Чтоб не писать std:: постоянно
можно писать
using namеspace std; // Делаем глобальным
iostream — файл в котором описаны в частности стандартные потоки ввода-вывода. std — пространство имён стандартной библиотеки в котором описаны данные потоки. Если открыть и посмотреть файл iostream, то можно увидеть следующий код:
_STD_BEGIN
где данные макросы:
#define _STD_BEGIN namespace std <
#define _STD_END >
соответственно всё что объявленно в файле iostream входит в данное пространство имён. Чтобы обратиться к данному пространству имён нужно использовать std:: или using namеspace std.Пространства имён используются для избегания конфликтов имён переменных, функций и т. д. . Скажем если есть код, написанный давно, ещё до существования данных потоков (например ещё на чистом СИ) , то пространство имён поможет избежать конфликта если в том коде использовалась переменная cout.
Почему с ‘using namespace std;’ в *.cpp-файлах может быть очень плохо
То, что написано ниже, для многих квалифицированных C++ разработчиков будет прекрасно известным и очевидным, но тем не менее, я периодически встречаю using namespace std; в коде различных проектов, а недавно в нашумевшей статье про впечатления от высшего образования было упомянуто, что студентов так учат писать код в вузах, что и сподвигло меня написать эту заметку.
Итак. многие слышали, что using namespace std; в начале файла в C++ считается плохой практикой и нередко даже явно запрещен в принятых во многих проектах стандартах кодирования. Касательно недопустимости использования using namespace в header-файлах вопросов обычно не возникает, если мы хоть немного понимаем, как работает препроцессор компилятора: .hpp-файлы при использовании директивы #include вставляются в код «как есть», и соответственно using автоматически распространится на все затронутые .hpp- и .cpp-файлы, если файл с ним был заинклюден хоть в одном звене цепочки (на одном из сайтов это метко обозвали «заболеванием передающимся половым путем«). Но вот про .cpp-файлы все не так очевидно, так что давайте еще раз разберем, что же именно здесь не так.
Для чего вообще придумали пространства имен в C++? Когда какие-то две сущности (типы, функции, и т.д.) имеют идентификаторы, которые могут конфликтовать друг с другом при совместном использовании, C++ позволяет объявлять пространства с помощью ключевого слова namespace. Всё, что объявлено внутри пространства имен, принадлежит только этому пространству имен (а не глобальному). Используя using мы вытаскиваем сущности какого-либо пространства имен в глобальный контекст.
А теперь посмотрим, к чему это может привести.
Допустим, вы используете две библиотеки под названием Foo и Bar и написали в начале файла что-то типа
. таким образом вытащив всё, что есть в foo:: и в bar:: в глобальное пространство имен.
Все работает нормально, и вы можете без проблем вызвать Blah() из Foo и Quux() из Bar. Но однажды вы обновляете библиотеку Foo до новой версии Foo 2.0, которая теперь еще имеет в себе функцию Quux().
Теперь у вас конфликт: и Foo 2.0, и Bar импортируют Quux() в ваше глобальное пространство имен. В лучшем случае это вызовет ошибку на этапе компиляции, и исправление этого потребует усилий и времени.
А вот если бы вы явно указывали в коде метод с его пространством имен, а именно, foo::Blah() и bar::Quux(), то добавление foo::Quux() не было бы проблемой.
Но всё может быть даже хуже!
В библиотеку Foo 2.0 могла быть добавлена функция foo::Quux(), про которую компилятор по ряду причин посчитает, что она однозначно лучше подходит для некоторых ваших вызовов Quux(), чем bar::Quux(), вызывавшаяся в вашем коде на протяжении многих лет. Тогда ваш код все равно скомпилируется, но будет молча вызывать неправильную функцию и делать бог весть что. И это может привести к куче неожиданных и сложноотлаживающихся ошибок.
Имейте в виду, что пространство имен std:: имеет множество идентификаторов, многие из которых являются очень распространенными (list, sort, string, iterator, swap), которые, скорее всего, могут появиться и в другом коде, либо наоборот, в следущей версии стандарта C++ в std добавят что-то, что совпадет с каким-то из идентификаторов в вашем существующем коде.
Если вы считаете это маловероятным, то посмотрим на реальные примеры со stackoverflow:
Вот тут был задан вопрос о том, почему код возвращает совершенно не те результаты, что от него ожидает разработчик. По факту там происходит именно описанное выше: разработчик передает в функцию аргументы неправильного типа, но это не вызывает ошибку компиляции, а компилятор просто молча использует вместо объявленной выше функции distance() библиотечную функцию std::distance() из std:: ставшего глобальным неймспейсом.
Второй пример на ту же тему: вместо функции swap() используется std::swap(). Опять же, никакой ошибки компиляции, а просто неправильный результат работы.
Что лучше использовать using std:: или остоянно приписывать std. [дубликат]
Слышал, что в C++ не следует использовать using namespace std . В связи с этим вопрос, как лучше делать? В начале программы написать:
Или перед каждым оператором писать std:: на протяжении всей программы, то есть:
Интересует прежде всего с точки зрения скорости работы программы и занимаевого ею места.
![]()
С точки зрения работы/занимаемого места — разницы никакой, ибо для компилятора это одно и то же.
С точки зрения стоит/не стоит — старайтесь не использовать using в заголовочных файлах. В файлах с реализацией вполне нормально использовать using , если кода там не супермного.
![]()
ИМХО. Лучше везде писать std:: и другие конкретные неймспэйсы, если программа использует не только стандартные библиотеки. Ну типа программы «Hello world»)) Но ведь тогда уже можно писать using namespace std; А если нет, то даже если в сторонних библиотеках имена не пересекутся, то вы сами можете случайно написать какой-нибудь тип данных или создать объект, название которого совпадет с чем-нибудь из подключенной библиотеки. А вариант using std::cin, using std::cout; , как по мне, вообще странный. Откуда знать, что именно эти имена не совпадут? А если несколько разработчиков работают над программой? Чтобы совсем исключить вариант совпадения имен лучше везде конкретно указывать какому пространству принадлежит данное имя. Ну так проще. ИМХО. Ну а компилятору вообще все равно, на размере файла это не скажется, а уж на производительности тем более.
![]()
Всё ещё ищете ответ? Посмотрите другие вопросы с метками c++ рефакторинг или задайте свой вопрос.
Site design / logo © 2022 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2022.6.10.42345
Нажимая «Принять все файлы cookie», вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.