Using namespace std для чего нужен

Изучаем C++. Часть 8. Библиотеки и пространства имён

Разбираемся, как ускорить работу с кодом в несколько раз, используя готовые решения.

Using namespace std для чего нужен. 29dbddf250c42489fb64767096bb7d6d. Using namespace std для чего нужен фото. Using namespace std для чего нужен-29dbddf250c42489fb64767096bb7d6d. картинка Using namespace std для чего нужен. картинка 29dbddf250c42489fb64767096bb7d6d

Using namespace std для чего нужен. b933b44d0cc08613517c34f278be8774. Using namespace std для чего нужен фото. Using namespace std для чего нужен-b933b44d0cc08613517c34f278be8774. картинка Using namespace std для чего нужен. картинка b933b44d0cc08613517c34f278be8774

Это восьмая часть из серии статей «Глубокое погружение в C++». В прошлой статье мы узнали, как хранить данные в массивах. Сегодня — ещё интереснее.

Недавно мы говорили о том, что многие функции уже написаны другими разработчиками и помещены в специальные библиотеки. Если такая библиотека входит в состав языка или находится в открытом доступе, то вы можете использовать все её возможности.

Это очень удобно, и многие специально пишут универсальные библиотеки, которые пригодятся в самых разных проектах. Давайте разберёмся с библиотеками подробнее и научимся создавать свои.

Using namespace std для чего нужен. kucheryaviy. Using namespace std для чего нужен фото. Using namespace std для чего нужен-kucheryaviy. картинка Using namespace std для чего нужен. картинка kucheryaviy

Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Пространства имён в C++

Пространство имён (англ. namespace) — это группа взаимосвязанных функций, переменных, констант, классов, объектов и других компонентов программы.

С самого начала изучения C++ мы используем команду std: cout, чтобы выводить данные в терминал. На самом деле команда называется просто cout, а std — это пространство имён, в котором она находится.

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

Вот пример создания пространства имён:

Мы объединяем в группу несколько разных команд и избегаем конфликтов имён. Это нужно, когда в какой-то из подключённых вами библиотек уже есть функция, например sum (). По пространству имён программа поймёт, какая именно функция вам нужна.

Если же вы хотите сократить код, то используйте команду using:

В данном случае команда говорит, что вам нужны имена из mynames и std, поэтому никакой ошибки выведено не будет.

Также после using можно указать не целое пространство имён, а только отдельную функцию или переменную:

Файлы заголовков в C++

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

Здесь нет функции main (), потому что этот код — не самостоятельная программа, а библиотека для других программ. Следовательно, точка входа здесь не нужна. Также мы не подключаем iostream, потому что не собираемся ничего выводить, но вы можете добавить в свой заголовок любые другие файлы.

Поместите mylib.h в папку, где находится ваша программа. Затем добавьте в начало кода команду:

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

Теперь вы можете использовать весь функционал из этой библиотеки:

Вот что будет выведено:

Using namespace std для чего нужен. 13371409062020 27e9aa5bdf801f94f7728fe14d1ac08405e5a691. Using namespace std для чего нужен фото. Using namespace std для чего нужен-13371409062020 27e9aa5bdf801f94f7728fe14d1ac08405e5a691. картинка Using namespace std для чего нужен. картинка 13371409062020 27e9aa5bdf801f94f7728fe14d1ac08405e5a691

Обратите внимание, что функция pow, как и другие математические функции, существует также и в библиотеке cmath.

Заключение

Библиотеки и пространства имён — это полезные инструменты для каждого разработчика. В интернете есть готовые решения для любых задач, поэтому многие работодатели ищут специалистов, которые разбираются в определённой библиотеке.

Если вы часто работаете над однотипными проектами, можете написать для себя библиотеку и подключать её во все проекты, чтобы ускорить работу. Однако новичкам стоит стараться писать код каждый раз заново — так вы сможете его постоянно переосмысливать и замечать то, чего раньше не замечали.

Если вы хотите освоить С++, то можете пройти наш курс. В нём все аспекты языка разбираются детально и на практике, а в конце каждого задания вы получаете обратную связь от преподавателей.

Источник

Пространство имен (using namespace std;)

5 ответов 5

Зависит от традиций. Среди плюсовиков традиция «лучше перестраховаться, чем получить внезапные трудно отлаживаемые проблемы неизвестно где».

Явное указание пространства имён — это избавление от потенциальных проблем в будущем. Положим, вы подключили через using namespace два пространства имён. Всё замечательно, кратко, красиво.

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

В лучшем случае ваш код не соберётся. Может упасть. А может так получиться, что ваш код перестанет работать у клиента в 1% случаев. Всё может быть.

Отлавливать и исправлять подобные проблемы мучительно больно.

Насколько это важно конкретно для вас — решать вам. Если у вас простой проектик и от силы пара сторонних библиотек (или вообще только стандартная библиотека), то можно не заморачиваться с явным указанием пространств имён. Если проект огромный, с десятками библиотек, то может оказаться более удобным (и наглядным) всегда указывать пространства имён.

Банальный пример: положим, вы пользуетесь только стандартной библиотекой и boost, поэтому решили везде писать:

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

В других языках другие традиции. Например, в C# почти всегда пишут краткие имена классов, и только в случае конфликтов явно указывают пространство имён или используют алиасы. Язык немного отличается: там нет функций вне классов. Это позволяет меньше терять читаемость и реже натыкаться на неожиданные конфликты.

Источник

Урок №53. Пространства имен

Этот урок является продолжением урока №24.

Конфликт имен

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

Рассмотрим пример такого конфликта. boo.h и doo.h — это заголовочные файлы с функциями, которые выполняют разные вещи, но имеют одинаковые имена и параметры.

Если boo.h и doo.h скомпилировать отдельно, то всё пройдет без инцидентов. Однако, соединив их в одной программе, мы подключим две разные функции, но с одинаковыми именами и параметрами, в одну область видимости (глобальную), а это, в свою очередь, приведет к конфликту имен. В результате, компилятор выдаст ошибку. Для решения подобных проблем и добавили в язык С++ такую концепцию, как пространства имен.

Что такое пространство имен?

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

Глобальная переменная g_z и функция boo() определены в глобальном пространстве имен.

В примере, приведенном выше, при подключении файлов boo.h и doo.h обе версии doOperation() были включены в глобальное пространство имен, из-за чего, собственно, и произошел конфликт имен.

Чтобы избежать подобных ситуаций, когда два независимых объекта имеют идентификаторы, которые могут конфликтовать друг с другом при совместном использовании, язык C++ позволяет объявлять собственные пространства имен через ключевое слово namespace. Всё, что объявлено внутри пользовательского пространства имен, — принадлежит только этому пространству имен (а не глобальному).

Перепишем заголовочные файлы из вышеприведенного примера, но уже с использованием namespace:

Результатом будет еще одна ошибка:

C:\VCProjects\Test.cpp(15) : error C2065: ‘doOperation’ : undeclared identifier

Случилось так, что когда мы попытались вызвать функцию doOperation(), компилятор заглянул в глобальное пространство имен в поисках определения doOperation(). Однако, поскольку ни одна из наших версий doOperation() не находится в глобальном пространстве имен, компилятор не смог найти определение doOperation() вообще!

Существует два разных способа сообщить компилятору, какую версию doOperation() следует использовать: через оператор разрешения области видимости или с помощью using-стейтментов (о них мы поговорим на следующем уроке).

Доступ к пространству имен через оператор разрешения области видимости (::)

Первый способ указать компилятору искать идентификатор в определенном пространстве имен — это использовать название необходимого пространства имен вместе с оператором разрешения области видимости ( :: ) и требуемым идентификатором.

Например, сообщим компилятору использовать версию doOperation() из пространства имен Boo :

Источник

Почему с ‘using namespace std;’ в *.cpp-файлах может быть очень плохо

То, что написано ниже, для многих квалифицированных C++ разработчиков будет прекрасно известным и очевидным, но тем не менее, я периодически встречаю using namespace std; в коде различных проектов, а недавно в нашумевшей статье про впечатления от высшего образования было упомянуто, что студентов так учат писать код в вузах, что и сподвигло меня написать эту заметку.

Для чего вообще придумали пространства имен в 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(). Опять же, никакой ошибки компиляции, а просто неправильный результат работы.

Так что подобное происходит гораздо чаще, чем кажется.

Источник

6.12 – Объявления using и директивы using

Вы, наверное, видели эту программу во многих учебниках и учебных руководствах:

Некоторые старые компиляторы также начинают новые проекты с аналогичной программы.

Если вы это видите, бегите. Возможно, ваш учебник, руководство или компилятор устарели. В этом уроке мы выясним, почему.

Краткий урок истории

Перенесемся в сегодняшний день – если вы много используете стандартную библиотеку, набирание std:: перед всем, что вы используете из стандартной библиотеки, может стать повторяющейся рутиной, а в некоторых случаях может затруднить чтение вашего кода.

Но сначала давайте определим два термина.

Полные и неполные имена

Имя может быть полным или неполным.

Полное имя – это имя, которое включает в себя связанную область видимости. Чаще всего имена дополняются пространством имен с помощью оператора разрешения области видимости ( :: ). Например:

Для продвинутых читателей

Неполное имя – это имя, которое не включает в себя квалификатор области видимости. Например, cout и x являются неполными именами, поскольку они не включают связанную область видимости.

Объявления using

Директивы using

Вот снова наша программа Hello World с директивой using в строке 5:

Директивы using – это решение, которое было предоставлено для баз старого кода до пространства имен, которые использовали неполные имена для функций стандартной библиотеки. Вместо того, чтобы вручную обновлять каждое неполное имя до полного имени (что было рискованно), можно было бы разместить одну директиву using (т.е. using namespace std; ) в верхней части каждого файла, и все имена, которые были перемещены в пространство имен std всё еще можно было использовать неполными.

Проблемы с директивами using

Однако для современного кода C++ директивы using дают немного выгоды (экономия на вводе текста) по сравнению с риском.

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

Для наглядности рассмотрим пример, в котором директивы using вызывают неоднозначность:

Вот еще один более коварный пример:

или использовалось объявление using вместо директивы using :

тогда наша программа вообще не имела бы никаких проблем.

Даже если директивы using не вызывают конфликтов имен сегодня, они делают код более уязвимым для будущих конфликтов. Например, если ваш код включает директиву using для какой-либо библиотеки, которая затем обновляется, все новые имена, представленные в обновленной библиотеке, теперь являются кандидатами на конфликты имен с вашим существующим кодом.

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

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

Когда компилятор встречает вызов функции, он должен определить, с каким определением функции он должен сопоставить этот вызов. При выборе функции из набора потенциально совпадающих функций он предпочтет ту функцию, которая не требует преобразования аргументов, а не ту, которая требует преобразования аргументов. Поскольку литерал 0 принадлежит целочисленному типу, C++ предпочтет сопоставить someFcn(0) с недавно добавленной someFcn(int) (без преобразований), а не с someFcn(double) (требуется преобразование из int в double). Это вызывает неожиданное изменение результатов работы нашей программы.

Этого бы не произошло, если бы мы использовали объявление using или явный квалификатор области видимости.

Область видимости объявлений и директив using

Если объявление using или директива using используется в блоке, имена применимы только в этом блоке (они следуют обычным правилам области видимости блока). Это хорошо, поскольку снижает вероятность возникновения конфликтов имен внутри этого блока.

Если объявление using или директива using используются в глобальном пространстве имен, имена применимы ко всему остальному файлу (они имеют область видимости файла).

Отмена или замена инструкции using

После объявления инструкции using ее невозможно отменить или заменить ее другой инструкцией using в той области видимости, в которой она была объявлена.

Лучшее, что вы можете сделать, – это намеренно с самого начала ограничить область видимости инструкции using с помощью правил области видимости блока.

Конечно, всей этой головной боли можно избежать, в первую очередь, используя явным образом оператор разрешения области видимости ( :: ).

Лучшие практики для инструкций using

В современном C++ на самом деле нет места для использования директив. Они увеличивают вероятность коллизий имен сейчас и в будущем и могут вызывать более коварные проблемы. Хотя во многих учебниках и руководствах они широко используются, использования директив лучше вообще избегать.

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

Лучшая практика

Источник

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

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