Как не писать std в c
Перейти к содержимому

Как не писать std в c

по С++: зачем нужен 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:: на протяжении всей программы, то есть:

Интересует прежде всего с точки зрения скорости работы программы и занимаевого ею места.

user avatar

С точки зрения работы/занимаемого места — разницы никакой, ибо для компилятора это одно и то же.

С точки зрения стоит/не стоит — старайтесь не использовать using в заголовочных файлах. В файлах с реализацией вполне нормально использовать using , если кода там не супермного.

user avatar

ИМХО. Лучше везде писать std:: и другие конкретные неймспэйсы, если программа использует не только стандартные библиотеки. Ну типа программы «Hello world»)) Но ведь тогда уже можно писать using namespace std; А если нет, то даже если в сторонних библиотеках имена не пересекутся, то вы сами можете случайно написать какой-нибудь тип данных или создать объект, название которого совпадет с чем-нибудь из подключенной библиотеки. А вариант using std::cin, using std::cout; , как по мне, вообще странный. Откуда знать, что именно эти имена не совпадут? А если несколько разработчиков работают над программой? Чтобы совсем исключить вариант совпадения имен лучше везде конкретно указывать какому пространству принадлежит данное имя. Ну так проще. ИМХО. Ну а компилятору вообще все равно, на размере файла это не скажется, а уж на производительности тем более.

user avatar

Всё ещё ищете ответ? Посмотрите другие вопросы с метками 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.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *