Std что это значит

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

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

Источник

/std (Укажите версию Standard языка)

Включить поддерживаемые возможности языка C и C++ из заданной версии стандарта языка C или C++.

Синтаксис

/std:c++14
/std:c++17
/std:c++20
/std:c++latest
/std:c11
/std:c17

Remarks

/std параметры доступны в Visual Studio 2017 и более поздних версиях. Они используются для управления стандартными функциями языка программирования ISO C или C++, включенными во время компиляции кода. С помощью этих параметров можно отключить поддержку некоторых новых возможностей языка и библиотеки. это может нарушить существующий код, который соответствует определенной версии стандарта языка.

Поддержка стандартов C++

/std Параметр, действующий во время компиляции C++, может быть обнаружен с помощью _MSVC_LANG макроса препроцессора. Дополнительные сведения см. в статье Макросы препроцессора.

/std:c++14
/std:c++14 параметр позволяет включить стандартные функции c++ 14, реализуемые компилятором MSVC. Этот параметр используется по умолчанию для кода, скомпилированного как C++. он доступен начиная с Visual Studio 2015 с обновлением 3.

следующие функции остаются включенными, если /std:c++14 указан параметр, чтобы избежать критических изменений для пользователей, которые уже применяют зависимости от функций, доступных в или до Visual Studio 2015 с обновлением 2.

/std:c++17
/std:c++17 Параметр включает стандартные функции и поведение c++ 17. он включает полный набор функций c++ 17, реализованный компилятором MSVC. Этот параметр отключает поддержку компилятора и стандартной библиотеки для новых или измененных функций после C++ 17. Он специально отключает изменения после + + 17 в стандарте C++ и версиях рабочего черновика. Он не отключает обновление ретроактивного дефектов стандарта C++. этот параметр доступен начиная с Visual Studio 2017 версии 15,3.

в зависимости от версии или уровня обновления компилятора MSVC компоненты c++ 17 могут быть полностью реализованы или полностью согласованы при указании /std:c++17 параметра. Общие сведения о согласовании языка C++ в Visual C++ по версии выпуска см. в разделе соответствие языку в Microsoft C/C++.

/std:c++20 Параметр отключает поддержку компилятора и стандартной библиотеки для новых или измененных функций после c++ 20. Он специально отключает изменения, внесенные после + + 20, в стандарте C++ и версии рабочего черновика. В нем не отключаются обновления ретроактивного дефектов стандарта C++.

/std:c++latest
/std:c++latest Параметр включает все реализованные в настоящее время компилятор и стандартные функции библиотеки, предлагаемые для следующего черновика, а также некоторые выполняющиеся и экспериментальные функции. этот параметр доступен начиная с Visual Studio 2015 с обновлением 3.

в зависимости от версии компилятора MSVC или уровня обновления, c++ 17, c++ 20 или предложенных функций c++ 23 могут быть не полностью реализованы или полностью согласованы при указании /std:c++latest параметра. мы рекомендуем использовать последнюю версию Visual Studio для максимального соответствия стандартам. Общие сведения о согласовании языка C++ и библиотеки в Visual C++ по версии выпуска см. в статье соответствие стандартам языка C/c++.

в версиях Visual Studio 2019 до версии 16,11 /std:c++latest требуется включить все функции компилятора и стандартной библиотеки c++ 20.

Список поддерживаемых возможностей языка и библиотеки см. в разделе новые возможности C++ в Visual Studio.

/std:c++latest Параметр не включает функции, защищенные /experimental коммутатором, но может потребоваться для их включения.

Функции компилятора и библиотеки, включенные в, /std:c++latest могут появиться в будущем стандарте C++. Неутвержденные возможности предоставляются на условиях «как есть», могут удаляться без уведомления либо в них могут вноситься критические изменения.

Поддержка стандартов C

/std:c11
/std:c11 Параметр позволяет включить соответствие ISO C11. он доступен начиная с Visual Studio 2019 версии 16,8.

/std:c17
/std:c17 Параметр позволяет включить соответствие ISO C17. он доступен начиная с Visual Studio 2019 версии 16,8.

Поскольку для поддержки этих стандартов требуется новый препроцессор, /std:c11 /std:c17 параметры компилятора и устанавливают /Zc:preprocessor параметр автоматически. Если вы хотите использовать традиционный (устаревший) препроцессор для C11 или C17, необходимо /Zc:preprocessor- явно задать параметр компилятора. Установка /Zc:preprocessor- параметра может привести к непредвиденному поведению и не рекомендуется.

на момент выпуска и до Visual Studio 2019 версии 16,10 библиотеки Windows SDK и UCRT, установленные Visual Studio, еще не поддерживают код C11 и C17. требуется обновленная версия Windows SDK и UCRT. Дополнительные сведения и инструкции по установке см. в разделе Установка поддержки C11 и C17 в Visual Studio.

при указании /std:c11 или /std:c17 MSVC поддерживает все функции C11 и C17, необходимые для стандартов. /std:c11 /std:c17 Параметры компилятора и обеспечивают поддержку этих функциональных возможностей:

так как C17 в основном является исправлением ошибок в версии ISO C11, MSVC поддержка C11 уже включает все соответствующие отчеты об ошибках. Различия между версиями C11 и C17, за исключением __STDC_VERSION__ макроса, отсутствуют. Он разворачивается в 201112L для C11 и 201710L для C17.

Компилятор не поддерживает большинство дополнительных функций ISO C11. некоторые из этих необязательных функций C11 были необходимыми функциями C99, которые MSVC не реализованы в целях архитектуры. Вы можете использовать макросы тестирования компонентов, например, __STDC_NO_VLA__ чтобы определить уровни поддержки компилятора для отдельных компонентов. Дополнительные сведения о предопределенных макросах для C см. в разделе предопределенные макросы.

Поддержка многопоточности, атомарных или комплексных чисел не поддерживается.

Дополнительные сведения см. в разделе функции стандартной библиотеки C в области соответствия языка Microsoft C/C++.

Установка данного параметра компилятора в среде разработки Visual Studio

Откройте диалоговое окно Страницы свойств проекта. Подробнее см. в статье Настройка компилятора C++ и свойств сборки в Visual Studio.

Источник

Урок №24. Конфликт имен и std namespace

Обновл. 11 Сен 2021 |

На этом уроке мы рассмотрим, что такое конфликт имен в языке C++ и как его решить с помощью пространств имен и оператора разрешения области видимости.

Конфликт имен в C++

Допустим, что вам нужно съездить к дальним родственникам в другой город. У вас есть только их адрес: г. Ржев, ул. Вербовая, 13. Попав в город Ржев, вы открываете Google Карты/Яндекс.Карты и видите, что есть две улицы с названием Вербовая, еще и в противоположных концах города! Какая из них нужна вам? Если у вас нет никакой дополнительной информации (например, вы знаете, что их дом находится возле аптеки или школы), вам придется позвонить им и спросить. Чтобы подобной путаницы не возникало, все названия улиц в городе должны быть уникальными.

Аналогично и в языке C++ все идентификаторы (имена переменных/функций/классов и т.д.) должны быть уникальными. Если в вашей программе находятся два одинаковых идентификатора, то будьте уверены, что ваша программа не скомпилируется: вы получите ошибку конфликта имен.

Пример конфликта имен:

По отдельности файлы a.cpp, b.cpp и main.cpp скомпилируются. Однако, если a.cpp и b.cpp разместить в одном проекте — произойдет конфликт имен, так как определение функции doSomething() находится сразу в обоих файлах.

Большинство конфликтов имен происходят в двух случаях:

Файлы, добавленные в один проект, имеют функцию (или глобальную переменную) с одинаковыми именами (ошибка на этапе линкинга).

Как только программы становятся больше, то и идентификаторов используется больше. Следовательно, вероятность возникновения конфликта имен значительно возрастает. Хорошая новость заключается в том, что язык C++ предоставляет достаточно механизмов для предотвращения возникновения конфликтов имен (например, локальная область видимости или пространства имен).

Пространство имен

В первых версиях языка C++ все идентификаторы из Стандартной библиотеки C++ (такие как cin/cout и т.д.) можно было использовать напрямую. Тем не менее, это означало, что любой идентификатор из Стандартной библиотеки С++ потенциально мог конфликтовать с именем, которое вы выбрали для ваших собственных идентификаторов. Код, который работал, мог внезапно получить конфликт имен при подключении нового заголовочного файла из Стандартной библиотеки С++. Или, что еще хуже, код, написанный по стандартам одной версии языка С++, мог уже не работать в новой версии языка С++. Чтобы устранить данную проблему, весь функционал Стандартной библиотеки С++ перенесли в специальную область — пространство имен (англ. «namespace»).

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

Мы еще поговорим о пространствах имен на следующих уроках, а также рассмотрим создание своего собственного пространства имен. Сейчас, главное, что вам нужно запомнить, — это то, что всякий раз, когда вы используете идентификаторы из Стандартной библиотеки С++ (например, cout), вы должны сообщать компилятору, что этот идентификатор находится внутри пространства имен std.

Правило: При использовании идентификаторов из пространства имен — указывайте используемое пространство имен.

Оператор разрешения области видимости ::

Источник

Неприятная особенность std::list, о которой не все знают

Двусвязный список — это фундаментальная структура данных, о которой все знают и повсеместно используют. Все знают почему и в каких случаях он эффективнее вектора, какие операции имеют линейную сложность, а какие — константную…

Хотя постойте, знаете ли вы какова сложность функции size ()?
«Конечно же я знаю — О(1)!», ответят многие из вас, «Что может быть проще?»

Тривиально, эффективно и безопасно, не так ли?
Я бы реализовал эту функцию именно так, большинство из вас сделали бы тоже самое.

Однако, те, кто писал реализацию GNU STL, другого мнения на этот счет.

Вот так выглядит реализация этой функции в gcc 4.x:

Если не верите — пойдите проверьте в своем дистрибутиве.

Что мы здесь видим? Чтобы выполнисть такую тривиальную операцию, как получение размера, наш список будет выполнять полный проход с подсчетом!

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

Вместо, казалось бы очевидного, O(N), мы получим здесь O(N^2). Хорошо если в списке 100 элементов. А что если 1 000 000?

Это так же значит, что вызов size () — небезопасен в многопоточной среде.

Имеем серьезный риск получить крэш в первом потоке.

Это так же значит, что

Так что же заставило программистов GNU реализовать список таким образом?

Оказывается, отсутствие необходимости поддерживать внутреннюю переменную _size позволяет реализовать splice за O(1), иначе было бы O(N) для худшего случая.

splice — это операция переноса последовательных элементов из одного списка в другой. Не имея необходимости подсчитывать новые размеры списков, нам достаточно «переключить» указатели с одних узлов на другие, т.е. за константное время.

Имея же внутреннюю переменную _size, нам бы пришлось посчитать сколько элементов мы переносим и соответсвенно обновить ее в обоих списках.

Вот такая вот причина. Кстати, как часто вы пользуетесь это операцией? А всеми вышеперечисленными?

Вобщем будте осторожнее. И еще имейте в виду, что в других реализациях STL переменная _size есть и size() соответственно работает за O(1). Так что будьте дважды осторожны, если вы собираете свой проект с разными реализациями STL на разных платформах.

На сем раскланиваюсь. Простите за ботанический пост в пятницу.

Источник

8.6.4. Стандартное пространство имен std

8.6.4. Стандартное пространство имен std

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

Если все компоненты библиотеки объявлены в std, то какая ошибка допущена в данном примере:

// привязка istream_iterator к стандартному вводу

istream_iteratorstring infile( cin );

// istream_iterator, отмечающий end-of-stream

// инициализация svec элементами, считываемыми из cin

vectorstring svec( infile, eos );

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

* заменить имена членов пространства std в этом примере соответствующими специфицированными именами;

* применить using-объявления, чтобы сделать видимыми используемые члены пространства std;

* употребить using-директиву, сделав видимыми все члены пространства std.

Членами пространства имен std в этом примере являются: шаблон класса istream_iterator, стандартный входной поток cin, класс string и шаблон класса vector.

Простейшее решение – добавить using-директиву после директивы препроцессора #include:

using namespace std;

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

Using-объявления, необходимые для компиляции этого примера, таковы:

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

В нашей книге мы не употребляли using-объявлений. Это сделано, во-первых, для того, чтобы сократить размер кода, а во-вторых, потому, что большинство примеров компилировались в реализации С++, не поддерживающей пространства имен. Подразумевается, что using-объявления указаны для всех членов пространства имен std, используемых в примерах.

Поясните разницу между using-объявлениями и using-директивами.

Напишите все необходимые using-объявления для примера из раздела 6.14.

Возьмем следующий фрагмент кода:

const int limit = 1000;

double dvar = 3.1416;

int iobj = limit + 1;

Каковы будут значения объявлений и выражений, если поместить using-объявления для всех членов пространства имен Exercise в точку //1? В точку //2? А если вместо using-объявлений использовать using-директиву?

2014-05-27 17:41:19 Николай

2012-08-28 16:06:54 Илья

2012-08-28 14:27:16 Илья

ch8.2.3 «. Чтобы это стало возможным, заголовочный файл не должен содержать объявлений встроенных (inline) функций и объектов. » «. Определения символических констант и встроенных функций являются специальными видами определений: те и другие могут появиться в программе несколько раз. » Возникает вопрос, верно ли написано в 1-й части? Если да, то как это пояснить?

Читайте также

Пространство имен XSL

6.3 Пространство имен устройств

6.3 Пространство имен устройств Данное пространство имен развилось за несколько лет существования Windows NT. Для обеспечения обратной совместимости новое пространство имен объединяется со старым пространством с помощью символических ссылок. Кроме того, драйверы режима

Пространство модели и пространство листа

Пространство модели и пространство листа Пространство модели (Model Space) – это пространство AutoCAD, где формируются модели объектов как при двумерном, так и при трехмерном моделировании. О том, что в окне AutoCAD на текущий момент установлено пространство модели, говорят

Пространство имен по умолчанию в Visual Studio 2005

Пространство имен по умолчанию в Visual Studio 2005 В заключение нашего обсуждения пространств имен следует отметить, что при создании нового C#-проекта в Visual Studio 2005 имя пространства имен вашего приложения по умолчанию будет совпадать с именем проекта. При вставке новых

Пространство имен System.Collections.Specialized

Пространство имен System.Collections.Generic

Пространство имен System.Threading

ГЛАВА 16. Пространство имен System.IO

Пространство имен System.Resources

Пространство имен System.ComponentModel

Пространство имен System.ComponentModel Пространство имен System.ComponentModel определяет целый ряд атрибутов (и других типов), позволяющих описать то, как должны вести себя ваши элементы управления в режиме проектирования. Например, вы можете указать текстовое описание каждого свойства,

Пространство имен System.Web.Services

Пространство модели и пространство листа

Пространство модели и пространство листа Пространство модели (Model Space) – это пространство AutoCAD, где формируются модели объектов как при двумерном, так и при трехмерном моделировании. О том, что в окне AutoCAD на текущий момент установлено пространство модели, говорят

Пространство имен оболочки

Пространство модели и пространство листа

Пространство модели и пространство листа Пространство модели (Model Space) – это пространство AutoCAD, где формируются модели объектов как при двумерном, так и при трехмерном моделировании. О том, что в окне AutoCAD на текущий момент установлено пространство модели, говорят

Пространство имен XSLT

Пространство имен XSLT Для того чтобы выделить элементы и атрибуты, которые принадлежат логической схеме XSLT, в этом языке применяется механизм пространств имен. Это означает, что в документе преобразования элементы, относящиеся к XSLT, должны принадлежать его пространству

Источник

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

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