Почему "использование пространства имен std;" считается плохой практикой? - PullRequest
2376 голосов
/ 21 сентября 2009

Мне говорили, что писать using namespace std; в коде неправильно, и что вместо этого я должен использовать std::cout и std::cin.

Почему using namespace std; считается плохой практикой? Это неэффективно или существует риск объявления неоднозначных переменных (переменных, которые имеют то же имя, что и функция в std пространстве имен)? Влияет ли это на производительность?

Ответы [ 36 ]

9 голосов
/ 31 декабря 2014

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

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout<<count<<endl;
}
8 голосов
/ 21 сентября 2009

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

7 голосов
/ 23 апреля 2018

Это не ухудшает производительность вашего программного обеспечения или проекта, включение пространства имен в начале вашего исходного кода неплохо. Включение инструкции using namespace std зависит от ваших потребностей и способа разработки программного обеспечения или проекта.

namespace std содержит стандартные функции и переменные C ++. Это пространство имен полезно, когда вы часто используете стандартные функции C ++.

Как упомянуто на этой странице :

Оператор, использующий пространство имен std, обычно считается плохим практика. Альтернативой этому утверждению является указание пространство имен, к которому относится идентификатор, с помощью оператора области действия (: :) каждый раз, когда мы объявляем тип.

И см. это мнение :

Нет проблем с использованием "using namespace std" в вашем исходном файле когда вы интенсивно используете пространство имен и точно знаете, что ничто не столкнется.

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

Как упомянуто на этой странице :

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

...

Теперь, на более поздней стадии разработки, мы хотим использовать другую версию Cout, который специально реализован в некоторой библиотеке под названием «Foo» (для пример)

...

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

6 голосов
/ 30 ноября 2017

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

6 голосов
/ 11 апреля 2013

С неквалифицированными импортированными идентификаторами вам нужны внешние инструменты поиска, такие как grep , чтобы узнать, где объявлены идентификаторы. Это усложняет рассуждения о правильности программы.

6 голосов
/ 13 мая 2013

"Почему 'использование пространства имен std;' считается плохой практикой в ​​C ++? "

Я говорю иначе: почему ввод 5 дополнительных символов для некоторых считается громоздким?

Рассмотрим, например, При написании части числового программного обеспечения, почему бы мне даже подумать о загрязнении моего глобального пространства имен, сократив общий «std :: vector» до «vector», когда «vector» является одним из наиболее важных понятий проблемной области?

6 голосов
/ 13 октября 2014

Я согласен с другими - это требует столкновения имен, двусмысленности, а затем факт менее явный. Хотя я вижу использование using, я предпочитаю ограничить его. Я также настоятельно рассмотрел бы то, на что указали некоторые другие:

Если вы хотите найти имя функции, которое может быть довольно распространенным именем, но вы хотите найти его только в пространстве имен std (или наоборот - вы хотите изменить все вызовы, которые НЕ находятся в пространстве имен std, namespace X, ...), тогда как вы предлагаете это сделать? Вы могли бы написать программу для этого, но не лучше ли потратить время на работу над самим проектом, чем на написание программы для поддержки вашего проекта?

Лично я на самом деле не против префикса std::. Мне больше нравится внешний вид, чем отсутствие его. Я не знаю, так ли это, потому что это явно и говорит мне: «Это не мой код ... Я использую стандартную библиотеку» или это что-то еще, но я думаю, что это выглядит лучше. Это может быть странно, учитывая, что я только недавно вошел в C ++ (использовал и все еще использую C и другие языки гораздо дольше, и C - мой любимый язык всех времен, прямо над сборкой).

Есть еще одна вещь, хотя она в некоторой степени связана с вышеизложенным и тем, на что указывают другие. Хотя это может быть плохой практикой, я иногда резервирую std::name для стандартной версии библиотеки и название для конкретной реализации программы. Да, действительно, это может укусить вас и укусить вас сильно, но все сводится к тому, что я начал этот проект с нуля, и я единственный программист для него. Пример: я перегружаю std::string и называю это string. У меня есть полезные дополнения. Я сделал это частично из-за моей склонности C и Unix (+ Linux) к именам в нижнем регистре.

Кроме того, у вас могут быть псевдонимы пространства имен. Вот пример того, где это полезно, на которое, возможно, не ссылались. Я использую стандарт C ++ 11 и специально с libstdc ++. Ну, у него нет полной поддержки std::regex. Конечно, он компилируется, но он выдает исключение, так как это ошибка программиста. Но это недостаток реализации. Вот как я это решил. Установите регулярное выражение Boost, свяжите его. Затем я делаю следующее, чтобы, когда libstdc ++ полностью его реализовал, мне нужно было только удалить этот блок, а код остался прежним:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;  
}

Я не буду спорить о том, плохая это идея или нет. Я, однако, буду утверждать, что он сохраняет его чистым для МОЕГО проекта и в то же время делает его конкретным: True, я должен использовать Boost, НО я использую его так, как в итоге у libstdc ++. Да, начинать собственный проект и начинать со стандартного (...) в самом начале очень долгий путь, помогая сопровождению, развитию и всему, что связано с проектом!

Изменить:
Теперь у меня есть время, чтобы кое-что прояснить. На самом деле я не думаю, что было бы хорошей идеей использовать имя класса / что-либо в STL намеренно и более конкретно вместо. Строка является исключением (игнорируйте первое, выше или второе здесь, каламбур, если нужно) для меня, так как мне не понравилась идея «String». На самом деле, я все еще очень склонен к С и склонен к С ++. Щадящие детали, большая часть того, над чем я работаю, больше подходит для C (но это было хорошее упражнение и хороший способ заставить себя а. Изучать другой язык и б) стараться не быть менее предвзятым по отношению к объекту / классам / и т. Д., Что, возможно, лучше сформулировано как менее закрытый, менее высокомерный, более принимающий.) Но что полезно, так это то, что некоторые уже предложили: я действительно использую list (это довольно универсально, не так ли?), Sort (то же самое), чтобы назвать два, которые вызвали бы конфликт имен, если бы я сделал using namespace std; и поэтому для этого я предпочитаю быть конкретным, контролировать и знать, что если я намерен использовать его как стандартное использование, мне придется его указать. Проще говоря: не предполагая, разрешено.

А что касается включения регулярного выражения Boost в std. Я делаю это для будущей интеграции и - опять же, я полностью признаю, что это предвзятость - я не думаю, что это так уродливо, как boost::regex:: ... На самом деле это для меня другое. В C ++ есть много вещей, которые мне еще предстоит полностью принять во взглядах и методах (еще один пример: шаблоны с переменными значениями по сравнению с аргументами var [хотя я допускаю, что шаблоны с переменными числами очень и очень полезны!]). Даже тем, кого я принимаю, было трудно, и у меня все еще есть проблемы с ними.

6 голосов
/ 21 сентября 2009

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

5 голосов
/ 21 августа 2016

Из моего опыта, если у вас есть несколько библиотек, которые используют, скажем, cout, но для другой цели вы можете использовать неправильный cout.

Например, если я наберу using namespace std; и using namespace otherlib; и введу просто cout (что происходит в обоих), а не std::cout (или 'otherlib::cout'), вы можете использовать неправильный, и получать ошибки, гораздо эффективнее и эффективнее использовать std::cout.

5 голосов
/ 28 июня 2013

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

Я имею в виду на самом деле ... говорить "не полагайся на это присутствие" - это просто настраивать тебя на то, чтобы оно НЕ присутствовало. У вас постоянно будут проблемы с заимствованием фрагментов кода и их постоянным исправлением. Просто держите ваши пользовательские и заимствованные вещи в ограниченном объеме, как они должны быть, и ОЧЕНЬ щадите глобальные (честно говоря, глобальные переменные почти всегда должны быть последним средством для целей «скомпилируйте сейчас, рассудите позже»). Действительно, я думаю, что это плохой совет от вашего учителя, потому что использование std будет работать как для "cout", так и для "std :: cout", но НЕ использование std будет работать только для "std :: cout". Вам не всегда повезет написать свой собственный код.

ПРИМЕЧАНИЕ: не зацикливайтесь на вопросах эффективности, пока вы не узнаете немного о том, как работают компиляторы. Имея небольшой опыт написания кода, вам не нужно много узнавать о них, прежде чем вы поймете, насколько они способны обобщить хороший код во что-то простое. Все так же просто, как если бы вы написали все это на C. Хороший код настолько сложен, насколько это необходимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...