Почему «используется пространство имен std;» считается плохой практикой?

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

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

21.09.2009 03:08:23
Не забудьте, что вы можете сделать: "используя std :: cout;" Это означает, что вам не нужно вводить std :: cout, но не вводить все пространство имен std одновременно.
Bill 21.09.2009 15:29:56
@a платный ботаник google-styleguide.googlecode.com/svn/trunk/… ссылка больше не работает. Похоже, новая ссылка google.github.io/styleguide/cppguide.html#Other_C++_Features
MCG 12.11.2016 03:30:12
Особенно плохо использовать 'использование пространства имен std' в области видимости файлов заголовка. Использование его в исходных файлах (* .cpp) в области действия файлов после всех включений не так уж плохо, поскольку его эффект ограничен одной единицей перевода. Еще менее проблематично использовать его внутри функций или классов, потому что его эффект ограничен областью действия функции или класса.
sh- 25.06.2017 14:37:57
Я бы обескуражить использовать директиву , но для определенных пространств имен нравятся std::literals::chrono_literals, Poco::Data:Keywords, Poco::Unitsи вещи , которые будут иметь дело с литералами или читаемостями трюками. Всякий раз, когда это находится в заголовке или файлах реализации. Я думаю, это может быть нормально в области функций, но кроме литералов и прочего, это бесполезно.
Ludovic Zenohate Lagouardette 19.07.2017 09:33:00
@Jon: Это не имеет никакого отношения к пространству имен, в частности. Мой акцент был сделан на «в области видимости файлов заголовка». Чтобы сформулировать это как совет: не используйте «использование пространства имен» (std или другое) в области видимости файлов заголовочных файлов. Можно использовать его в файлах реализации. Извините за двусмысленность.
sh- 9.04.2018 14:10:17
30 ОТВЕТОВ
РЕШЕНИЕ

Это никак не связано с производительностью. Но учтите это: вы используете две библиотеки с именами Foo и Bar:

using namespace foo;
using namespace bar;

Все отлично работает, и вы можете позвонить Blah()из Foo и Quux()из бара без проблем. Но однажды вы обновляетесь до новой версии Foo 2.0, которая теперь предлагает функцию под названием Quux(). Теперь у вас есть конфликт: Foo 2.0 и Bar импортируются Quux()в ваше глобальное пространство имен. Это займет некоторое усилие, чтобы исправить, особенно если параметры функции совпадают.

Если бы вы использовали foo::Blah()и bar::Quux(), то введение foo::Quux()было бы не событие.

2198
19.09.2019 22:23:42
Мне всегда нравился Python "import big_honkin_name as bhn", так что вы можете просто использовать "bhn.something", а не "big_honkin_name.something" - действительно сократить ввод текста. Есть ли в C ++ что-то подобное?
paxdiablo 21.09.2009 03:18:02
Пространство имен @Pax io = boost :: filesystem;
AraK 21.09.2009 03:19:37
Я думаю, что это преувеличение, сказать, что это «какое-то усилие, чтобы исправить». У вас не будет экземпляров нового foo :: Quux, поэтому устраните неоднозначность всех ваших текущих применений с помощью bar :: Quux.
MattyT 21.09.2009 13:44:57
Может ли какой-нибудь разумный человек создать библиотеку с типами, чье неквалифицированное имя конфликтует с типами std?
erikkallen 21.09.2009 19:14:06
@TomA: Проблема в #defineтом, что он не ограничивается пространством имен, а попирает всю базу кода. Псевдоним пространства имен - это то, что вы хотите.
sbi 25.09.2009 08:28:23

Другая причина - это сюрприз.

Если я вижу cout << blah, а std::cout << blahне думаю: что это cout? Это нормально cout? Это что-то особенное?

49
19.09.2019 22:24:21
Это шутка? Я искренне не могу сказать. Если нет, то я лично предположил бы, что это нормальное «бодрствование», если вы не доверяете коду, так как в противном случае это было бы запаха кода BEYOND MAJOR, IMO. ... А если вы не доверяете коду, то почему вы используете его в первую очередь? Обратите внимание, что я не говорю "ДОВЕРЯЙТЕ ВСЕМ !!" но это также кажется немного надуманным, если вы, скажем, имеете дело с какой-то известной библиотекой из GitHub или чем-то еще.
Brent Rittenhouse 5.03.2018 22:43:25
@BrentRittenhouse cout- плохой пример, потому что все это признают. Но представьте себе futureв финансовом приложении. Это договор на покупку или продажу чего-либо на указанную дату? Нет, это не так. Если бы в коде говорилось, что std::futureвас не так легко спутать.
James Hollis 5.04.2018 20:20:38
@BrentRittenhouse может быть немного плохой пример, есть как минимум четыре разных библиотеки, которые имеют cout. Может быть "это стандартная библиотека? Libstdc ++? Stl? Что-то еще?" И нет, не все знают std :: cout, по крайней мере, по сути, 6 из 7 новых работников, которых мы получаем, не делают. Потому что учебные программы не используют их в образовании. Я должен прогнать printfs. Или отладки () - из Qt.
Swift - Friday Pie 24.04.2018 18:49:58
В самом деле? Это в значительной степени первый пример первой главы о многих книгах по С ++, во всяком случае, это (с использованием оператора вставки) единственный C ++, который знают некоторые новые боды.
mckenzm 29.07.2019 05:07:19
@mckenzm Я мог бы поместить это в книгу или примечания к лекции, чтобы уменьшить беспорядок, но не в коде
Martin Beckett 30.07.2019 22:48:07

Все дело в управлении сложностью. Использование пространства имен приведет к ненужным вещам и, следовательно, усложнит отладку (я говорю, возможно). Использование std :: повсеместно труднее для чтения (больше текста и все такое).

Лошади для курсов - управляй своей сложностью так, как ты можешь и можешь чувствовать себя лучше.

22
25.02.2014 19:40:31

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

6
11.10.2015 10:18:06

Рассматривать

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // Uh oh
};

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

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

18
19.09.2019 22:28:01

Проблема с размещением using namespaceзаголовочных файлов ваших классов состоит в том, что это заставляет любого, кто хочет использовать ваши классы (включая ваши заголовочные файлы), также «использовать» (то есть видеть все в) эти другие пространства имен.

Тем не менее, вы можете свободно использовать оператор using в ваших (приватных) * .cpp файлах.


Имейте в виду, что некоторые люди не согласны с моим высказыванием «не стесняйтесь», как это - потому что, хотя usingутверждение в файле cpp лучше, чем в заголовке (потому что это не влияет на людей, которые включают ваш заголовочный файл), они думают, что это не так хорошо (потому что в зависимости от кода это может усложнить реализацию класса). Эта запись C ++ Super-FAQ гласит:

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

FAQ предлагает две альтернативы:

  • Декларация об использовании:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • Просто наберите std ::

    std::cout << "Values:";
410
30.10.2019 03:54:15
Конечно, вы никогда не должны принимать состояние глобального cout, иначе кто-то имеет std: cout << std :: hex и впоследствии не сможет выполнить std :: restore_cout_state. Но это совсем другой фатберг.
Móż 2.11.2019 09:13:56

Если импортировать нужные файлы заголовков вы вдруг имена , как hex, left, plusили countв вашем глобальном масштабе. Это может быть удивительно, если вы не знаете, что std::содержит эти имена. Если вы также попытаетесь использовать эти имена локально, это может привести к некоторой путанице.

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

79
31.08.2013 22:17:41
+1 не говоря уже distance. тем не менее, я предпочитаю неквалифицированные имена там, где это практически возможно, поскольку это повышает читабельность для меня. Кроме того, я думаю, что тот факт, что мы обычно не квалифицируем вещи в устной речи и готовы тратить время на устранение возможных двусмысленностей, означает, что имеет смысл уметь понимать то, о чем идет речь, без оговорок и применяться к источнику код, который означает, что он структурирован таким образом, что понятно, о чем идет речь, даже без квалификации.
Cheers and hth. - Alf 15.12.2012 05:49:09
Чтобы быть справедливым, у вас не будет большинства из них, если вы не включите <iomanip>. Тем не менее, хороший момент.
einpoklum 24.02.2016 16:42:12

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

8
21.09.2009 03:34:06
  1. Вы должны уметь читать код, написанный людьми, которые придерживаются мнения, отличного от вашего стиля и лучших практик.

  2. Если вы только используете cout, никто не запутается. Но когда у вас много летающих пространств имен, и вы видите этот класс, и вы не совсем уверены, что он делает, явное использование пространства имен действует как своего рода комментарий. На первый взгляд вы можете видеть: «О, это операция с файловой системой» или «Это делает сетевые вещи».

18
19.09.2019 22:30:48

Я согласен со всем, что написал Грег , но я хотел бы добавить: это может быть даже хуже, чем сказал Грег!

Библиотека Foo 2.0 может представить функцию, Quux()которая однозначно лучше подходит для некоторых ваших вызовов, Quux()чем bar::Quux()ваш код, вызываемый годами. Тогда ваш код все еще компилируется , но он молча вызывает неправильную функцию и выполняет бог-знает-что. Это настолько плохо, насколько это возможно.

Имейте в виду , что stdпространство имен имеет тонн идентификаторов, многие из которых являются очень распространенными из них (думаю list, sort, string, iteratorи т.д.) , которые очень вероятно, появится в другом коде тоже.

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


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

За десятилетие этот проект вырос до нескольких миллионов строк кода. Поскольку эти обсуждения возникают снова и снова, мне однажды было любопытно, как часто (разрешенная) область действия функции usingфактически использовалась в проекте. Я нашел источники для него и нашел только одно или два десятка мест, где он использовался. Для меня это означает, что после std::попытки разработчики не находят достаточно болезненным применение директив даже один раз каждые 100 килокалорий, даже там, где это разрешено использовать.


Итог: явный префикс всего не приносит никакого вреда, требует очень мало привыкания и имеет объективные преимущества. В частности, это облегчает интерпретацию кода компилятором и читателями - и это, вероятно, должно быть главной целью при написании кода.

1377
27.03.2018 20:31:03
Это значительно ухудшает плотность кода, который вы можете упаковать в одну строку. Вы заканчиваете тем, что пишете свой код очень многословным способом; что снижает читабельность Лично я думаю, что более короткий (но не слишком короткий) код имеет тенденцию быть более читабельным (так как там меньше материала для чтения и меньше вещей, которые нужно отвлекать).
Lie Ryan 28.10.2010 15:13:41
Думаю, вы упустили старые времена, когда в C ++ не было стандартного stringкласса, и, похоже, у каждой библиотеки был свой. Скажем вам, что: Мы будем продолжать писать наш код std::, и вы сможете запускать наш код grep -v std:: | vim, просматривая его. Или вы можете научить своего редактора std::использовать ключевое слово, цвет которого должен соответствовать цвету фона. Что бы ни работало.
Mike DeSimone 28.10.2010 17:31:00
Я не думаю, что это std::вообще вредно. Он несет очень важную информацию (а именно: «все, что приходит после, является частью стандартной библиотеки», и это все еще довольно короткий и компактный префикс. В большинстве случаев это вообще не проблема. Иногда у вас есть несколько строк кода где вам нужно часто обращаться к определенным символам в stdпространстве имен, а затем usingоператор в этой конкретной области решает проблему хорошо, но в общем случае это не шум, он передает ценную информацию в дополнение к устранению неоднозначностей.
jalf 28.10.2010 18:39:13
Всякий раз, когда я вижу std::, я знаю, что это произойдет std::без необходимости думать об этом. Если я вижу stringили listили mapсами по себе, я немного удивляюсь.
Mateen Ulhaq 14.09.2011 06:50:42
@LieRyan Тогда удачи в написании библиотеки геометрии, не называя ничего vector, transformили distance. И это только примеры многих очень распространенных имен, используемых в стандартной библиотеке. Предложение не использовать их из-за страха или предвзятого мнения о функции пространства имен, являющейся неотъемлемой частью C ++, довольно контрпродуктивно.
Chris says Reinstate Monica 7.03.2013 17:04:46

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

Однако, если я часто использую 'cout' и 'cin', я пишу: using std::cout; using std::cin;в файле .cpp (никогда в заголовочном файле, с которым он распространяется #include). Я думаю, что никто в здравом уме никогда не назовет поток coutили cin. ;)

29
19.09.2019 22:35:59
Это локальное объявление об использовании , совершенно отличное от использования директивы .
sbi 26.05.2012 06:41:08

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

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; // No problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

Это лучше, чем явная квалификация ( std::sin, std::cos...), потому что она короче и способна работать с определенными пользователем типами с плавающей запятой (через поиск по аргументам (ADL)).

121
19.09.2019 22:37:20
Извините, но я категорически не согласен с этим.
Billy ONeal 5.12.2010 17:15:07
@Billy: нет другого способа поддержать вызов userlib :: cos (userlib :: superint). Каждая функция имеет применение.
Zan Lynx 24.06.2011 23:42:32
@Zan: Конечно, есть. using std::cos;, using std::sinИ т.д. Проблема , однако, что любая хорошо продуманы userlibбудет иметь их sinи cosв их собственном пространстве имен, так что это на самом деле не поможет. (Если только не существует using namespace userlibдо этого шаблона, и это так же плохо, как using namespace std- и область его действия не ограничена.) Кроме того, единственная подобная функция, с которой я когда-либо сталкивался, это swap, и в таких случаях я бы рекомендовал просто создать шаблон Специализация std::swapи избежание всей проблемы.
Billy ONeal 24.06.2011 23:48:07
@BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)(Там нет частичной специализации шаблона функции (FTPS), поэтому иногда вам приходится прибегать к перегрузке.
sbi 30.05.2012 14:56:46
@BillyONeal: Ваш (7-кратный голос!) Комментарий неправильный - описанная вами ситуация - именно то , для чего ADL был разработан. Вкратце, если xимеется одно или несколько «связанных пространств имен» (например, если оно было определено в namespace userlib), то любой вызов функции, который выглядит как, cos(x)будет дополнительно выглядеть в этих пространствах имен - без необходимости в этом using namespace userlib;заранее. Zan Lynx прав (и поиск имени в C ++ византийский ...)
j_random_hacker 4.09.2015 15:31:07

Недавно я столкнулся с жалобой на Visual Studio 2010 . Оказалось, что почти все исходные файлы имеют следующие две строки:

using namespace std;
using namespace boost;

Многие функции Boost входят в стандарт C ++ 0x, а Visual Studio 2010 имеет много функций C ++ 0x, поэтому неожиданно эти программы не компилировались.

Следовательно, избегание using namespace X;- это форма проверки будущего, способ убедиться, что изменение используемых библиотек и / или заголовочных файлов не приведет к поломке программы.

232
11.10.2015 10:33:18
Эта. Boost и std имеют много общего - особенно начиная с C ++ 11.
einpoklum 24.02.2016 16:40:46
Я сделал это однажды и усвоил урок трудным путем. Теперь я никогда не использую usingвне определения функции и редко использую using namespaceвообще.
Ferruccio 10.04.2018 13:45:28

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

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

Каковы эти веские причины ? Иногда программисты явно хотят отключить ADL, иногда они хотят устранить неоднозначность.

Итак, все в порядке:

  1. Директивы использования на уровне функций и объявления использования внутри реализаций функций
  2. Объявления использования на уровне исходного файла внутри исходных файлов
  3. (Иногда) директивы using уровня исходного файла
45
16.04.2018 20:53:41

Не используйте это глобально

Считается «плохим» только при глобальном использовании . Потому что:

  • Вы загромождаете пространство имен, в котором программируете.
  • Читателям будет трудно увидеть, откуда исходит конкретный идентификатор, когда вы используете много using namespace xyz.
  • То, что верно для других читателей вашего исходного кода, еще более верно для самого частого читателя: вас самих. Вернитесь через год или два и посмотрите ...
  • Если вы говорите только о себе, using namespace stdвы можете не знать обо всех вещах, которые вы захватываете - и когда вы добавляете другую #includeили переходите на новую версию C ++, вы можете получить конфликты имен, о которых вы не знали.

Вы можете использовать его локально

Идите вперед и используйте его локально (почти) свободно. Это, конечно, мешает вам повторять std::- и повторение тоже плохо.

Идиома для его локального использования

В C ++ 03 была идиома - шаблонный код - для реализации swapфункции для ваших классов. Было предложено, чтобы вы на самом деле использовали местный using namespace std- или, по крайней мере using std::swap:

class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

Это делает следующую магию:

  • Компилятор выбрать std::swapFOR value_, то есть void std::swap(int, int).
  • Если у вас void swap(Child&, Child&)реализована перегрузка, компилятор выберет ее.
  • Если вы не имеете , что перегрузка компилятор будет использовать void std::swap(Child&,Child&)и попробовать все эти замены.

В C ++ 11 больше нет причин использовать этот шаблон. Реализация std::swapбыла изменена, чтобы найти потенциальную перегрузку и выбрать ее.

97
6.07.2017 07:35:50
«Реализация std :: swap была изменена, чтобы найти потенциальную перегрузку и выбрать ее». - Какая? Вы уверены, что? Хотя это правда, что предоставление кастома swapв первую очередь не так уж важно в C ++ 11, поскольку std::swapсам он более гибок (использует семантику перемещения). Но std::swapавтоматически выбирая свой собственный своп, это абсолютно ново для меня (и я не очень в это верю).
Chris says Reinstate Monica 7.03.2013 17:09:40
@ChristianRau Я так думаю, да. Я читал это на SO где-то. Мы всегда можем спросить Говарда , он должен знать. Я копать и копать сейчас ...
towi 8.03.2013 08:44:45
Даже в случае со свопом, более ясная (и, к счастью, более распространенная) идиома - писать, using std::swap;а не using namespace std;. Более конкретная идиома имеет меньше побочных эффектов и, следовательно, делает код более понятным.
Adrian McCarthy 27.02.2014 17:24:44
Последнее предложение неверно. В C ++ 11 Std Swap Two Step был официально благословлен как правильный способ вызова swap, и различные другие места в стандарте были изменены, чтобы сказать, что они называют swapтак (NB, как указано выше, using std::swapправильный путь, а не using namespace std). Но std::swapсамо по себе не изменилось, чтобы найти другого swapи использовать его. Если std::swapвызывается, то std::swapпривыкает.
Jonathan Wakely 16.07.2015 10:59:56
Возможно, было бы разумнее просто вводить using std::swapлокально, чтобы уменьшить локальное пространство имен и одновременно создать самодокументируемый код. Вы редко когда-либо интересовались всем пространством имен std, поэтому просто выберите интересующие вас части.
Lundin 26.10.2015 11:02:03

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

В конце концов, мне пришлось обойти это другими способами и сделать код менее понятным.

4
11.10.2015 10:42:10

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

6
11.04.2013 14:22:33

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

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

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

6
19.09.2019 22:49:27
Это не просто 5 дополнительных символов; его 5 дополнительных символов каждый раз, когда вы ссылаетесь на любой тип объекта в стандартной библиотеке. Что, если вы используете стандартную библиотеку очень часто, будет часто. Так что в программе приличного размера более реалистично тысячи дополнительных символов. Предположительно, в язык была добавлена ​​директива using, чтобы ее можно было использовать ...
Jeremy Friesner 3.09.2013 03:42:55
Это не 5 дополнительных символов каждый раз, это 5 символов и, возможно, пара щелчков мыши, чтобы открыть меню и выполнить поиск и замену в редакторе по вашему выбору.
DaveWalley 6.03.2014 01:54:36
Читаемость. cout << hex << setw(4) << i << endl;легче читать, чемstd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz 24.10.2014 09:47:48
И даже хуже: std::map<std::string,std::pair<std::string,std::string>>это ужасно по сравнению с map<string,pair<string,string>>.
oz1cz 24.10.2014 10:41:19
Хорошей практикой является в любом случае типизировать ваши контейнеры STL, так что std :: там действительно не имеет значения. А в C ++ 11 появилось ключевое слово auto, которое еще проще, например, при использовании итераторов.
juzzlin 19.01.2016 12:04:17

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

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

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

5
27.06.2013 20:33:03
Учитывая, что многие люди, кажется, не знают о полезных стандартных функциях библиотеки (например, заново изобретают что-то <algorithm>), кажется немного натянутой мысль, что одни и те же люди могут надежно избегать этих идентификаторов. Посмотрите свой собственный код и скажите, что у вас никогда не было вызванной переменной или функции count. Или distance, или log, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, leftи т.д. Не говоря уже о всех идентификаторах еще не в stdтом , что нарушит ваш код , когда C ++ 35 выходит ...
Toby Speight 23.05.2018 08:37:00

Я согласен, что это не должно использоваться глобально, но это не так плохо, чтобы использовать локально, как в namespace. Вот пример из "языка программирования C ++" :

namespace My_lib {

    using namespace His_lib; // Everything from His_lib
    using namespace Her_lib; // Everything from Her_lib

    using His_lib::String; // Resolve potential clash in favor of His_lib
    using Her_lib::Vector; // Resolve potential clash in favor of Her_lib

}

В этом примере мы разрешили потенциальные конфликты имен и неясности, возникающие из-за их состава.

Имена, явно объявленные там (включая имена, объявленные с помощью объявлений-использования His_lib::String), имеют приоритет над именами, доступными в другой области с помощью директивы using- using namespace Her_lib) ( ).

43
19.09.2019 22:53:02

Я думаю, что использование локально или глобально должно зависеть от приложения.

Потому что, когда мы используем библиотеку локально, иногда код будет настоящим беспорядком. Читаемость будет низкой.

Таким образом, мы должны использовать библиотеки локально только тогда, когда есть вероятность конфликтов.

Я не более опытный человек. Итак, дайте мне знать, если я ошибаюсь.

2
19.09.2019 22:54:07

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

Так что просто рассматривайте их функции как зарезервированные имена, такие как «int» или «class», и все.

Люди должны перестать быть такими анальными по этому поводу. Ваш учитель был прав с самого начала. Просто используйте одно пространство имен; в этом весь смысл использования пространств имен на первом месте. Вы не должны использовать более одного одновременно. Если только это не ваше. Итак, еще раз, переопределение не произойдет.

17
11.10.2015 10:44:02
Создание столкновений не так сложно - короткие строки нравится min, endи lessпоявляются в std::пространстве имен. Более того, теперь, когда в std::нем тысячи символов, читателю полезно знать, откуда появился новый символ, который они могут не знать.
Tom Swirly 24.05.2016 23:32:42
Пространство имен std существует потому, что люди, вы, ваши коллеги или люди, пишущие промежуточное программное обеспечение, которое вы используете, не всегда мудры в размещении функций внутри пространств имен. Таким образом, вы можете импортировать все std :: и ничего больше, в то же время вызывая коллизию между, скажем, std :: min и чьим-либо наследием :: min () до того времени, когда он был в std.
Aiken Drum 23.08.2017 14:22:13

Приятно видеть код и знать, что он делает. Если я вижу, std::coutя знаю, что это coutпоток stdбиблиотеки. Если я увижу, coutя не знаю. Это может быть coutпоток stdбиблиотеки. Или может быть на int cout = 0;десять строк выше в той же функции. Или staticпеременная с именем coutв этом файле. Это может быть что угодно.

Теперь возьмем базу кода в миллион строк, которая не особенно велика, и вы ищете ошибку, что означает, что вы знаете, что в этом миллионе строк есть одна строка, которая не выполняет то, что должна делать. cout << 1;мог прочитать static intимя cout, сдвинуть его влево на один бит и выбросить результат. В поисках ошибки, я должен это проверить. Вы видите, как я на самом деле предпочитаю видеть std::cout?

Это одна из тех вещей, которая кажется действительно хорошей идеей, если вы учитель и вам никогда не приходилось писать и поддерживать какой-либо кодекс для жизни. Мне нравится смотреть код, где (1) я знаю, что он делает; и (2) я уверен, что человек, который его написал, знал, что он делает.

25
29.03.2018 12:47:01
Откуда вы знаете, что std :: cout << 1 не читает статическое int с именем cout в пространстве имен std, сдвигая его на единицу и выбрасывая результат? Кроме того, как вы знаете, что "<<" делает;) ??? ... кажется, что этот ответ не является хорошей точкой данных, чтобы избежать "использования".
nyholku 11.06.2015 12:43:12
Если кто-то переопределил std :: cout как целое число, то ваша проблема не техническая, а социальная - у кого-то это есть для вас. (и вам, вероятно, также следует проверить все заголовки на наличие таких вещей, как #define true false и т. д.)
Jeremy Friesner 7.07.2016 04:33:35
Когда я вижу cout, я всегда знаю, что это std :: cout. Если я ошибаюсь, это проблема человека, который написал этот код, а не меня :)
Tien Do 31.08.2018 04:52:20

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

Если вы хотите найти имя функции, которое может быть довольно распространенным именем, но вы хотите найти его только в stdпространстве имен (или наоборот - вы хотите изменить все вызовы, которые не находятся в пространстве имен std, пространстве имен 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;
}

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

Просто чтобы прояснить кое-что: на самом деле я не думаю, что было бы хорошей идеей использовать имя класса / что-либо в STL намеренно и более конкретно вместо. Строка является исключением (игнорируйте первое, выше или второе здесь, каламбур, если нужно) для меня, поскольку мне не понравилась идея «String».

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

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

7
19.09.2019 23:03:03
Расширение stdпространства имен является неопределенным поведением и, следовательно, никогда не должно выполняться.
tambre 22.06.2018 13:42:31

Краткая версия: не используйте глобальные usingобъявления или директивы в заголовочных файлах. Не стесняйтесь использовать их в файлах реализации. Вот что Херб Саттер и Андрей Александреску должны сказать об этой проблеме в стандартах кодирования C ++ (выделение для акцента - мое):

Резюме

Использование пространства имен для вашего удобства, а не для того, чтобы вы навязывали его другим. Никогда не пишите объявление использования или директиву использования перед директивой #include.

Следствие: в заголовочных файлах не пишите на уровне пространства имен, используя директивы или объявления; вместо этого явно определите пространство имен для всех имен. (Второе правило следует из первого, потому что заголовки никогда не могут знать, какие другие заголовки #include могут появиться после них.)

обсуждение

Вкратце: вы можете и должны использовать пространство имен, свободно используя объявления и директивы в ваших файлах реализации после директив #include, и вам это нравится. Несмотря на неоднократные утверждения об обратном, пространства имен, использующие декларации и директивы, не являются злом и не наносят ущерба цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования .

208
19.09.2019 23:05:03
Еще одно мнение программиста, но, хотя я полностью согласен с утверждением, что слово usingникогда не должно появляться в заголовке, я не настолько убежден в том, что свободная лицензия может быть размещена using namespace xyz;где-либо в вашем коде, особенно если она xyzесть std. Я использую using std::vector;форму, так как она тянет только один элемент из пространства имен в псевдоглобальную область, что приводит к гораздо меньшему риску столкновения.
dgnuff 23.02.2016 23:51:55
@Lightness Races на орбите вы, конечно, имеете право на свое мнение. Было бы более полезно, если бы была попытка объяснить, почему вы не согласны с советом, данным в этом ответе. Особенно было бы интересно понять, в чем смысл пространств имен, если «использовать» их плохо? Почему бы просто не назвать вещи std_cout вместо std :: cout ... создатели пространства имен C ++ / должны были иметь некоторое представление, когда они пытались их создать.
nyholku 20.06.2016 13:36:29
@nyholku: Нет необходимости - большинство других ответов приводят те же причины, что и я. Также, пожалуйста, не стесняйтесь отметить ":)", который я добавил к моему комментарию! И что я не сказал, что пространства имен плохие.
Lightness Races in Orbit 20.06.2016 14:03:31
Да, я заметил это :), но IMO, большинство ответов (которые идут вразрез с этим мудрым советом) ошибочны (не то, чтобы я делал какие-либо статистические данные о том, какое большинство сейчас). Если вы согласны с тем, что пространство имен «неплохо», то вы можете сказать, где, по вашему мнению, они подходят, если вы не согласны с этим ответом?
nyholku 20.06.2016 16:54:40
Я не могу не чувствовать, что using namespaceзло подобно gotoзлу. Оба имеют действительное использование, но 999 раз из 1000 они будут использованы неправильно. Так что, да, с using namespaceисточником вы не будете загрязнять пространство имен других включений, аккуратно. Но это по-прежнему не защитит вас от «веселья» , возникающего из-за using namespace Foo+, using namespace Barкогда вы звоните (неявный Foo: :), baz(xyz)и внезапно ломает код (без связанных изменений) только потому, что он Bar::baz()был добавлен куда-то, что просто лучше совпадение (и, следовательно, теперь
CharonX 9.01.2020 08:58:03

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

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}
10
19.09.2019 23:06:49
::count--задача решена. Обычно из пространства имен std у вас будет больше информации, чем из других мест, поэтому сохранение директивы using namespace может спасти вам ввод текста.
PSkocik 11.07.2015 19:12:46
Настоящая проблема здесь в том, что в C ++ все еще есть глобалы без пространства имен. Это и тот факт, что «this» неявно присутствует в методах, вызывает столько ошибок и проблем, что я даже не могу их сосчитать, даже с правильной переменной «count». ;)
Aiken Drum 23.08.2017 14:27:34

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

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

// Header
class File
{
   typedef std::vector<std::string> Lines;
   Lines ReadLines();
}

и в реализации:

// .cpp
Lines File::ReadLines()
{
    Lines lines;
    // Get them...
    return lines;
}

в отличие от:

// .cpp
vector<string> File::ReadLines()
{
    vector<string> lines;
    // Get them...
    return lines;
}

или:

// .cpp
std::vector<std::string> File::ReadLines()
{
    std::vector<std::string> lines;
    // Get them...
    return lines;
}
13
19.09.2019 23:08:19
Просто небольшой комментарий, хотя typedef полезен, я бы подумал о создании класса, представляющего строки вместо использования typedef.
Eyal Solnik 11.03.2016 09:23:35

Пространство имен - это именованная область. Пространства имен используются для группировки связанных объявлений и для разделения отдельных элементов. Например, две отдельно разработанные библиотеки могут использовать одно и то же имя для ссылки на разные элементы, но пользователь все равно может использовать оба:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    // ...
}

namespace Yourlib{
    class Stack{ /* ... */ };
    // ...
}

void f(int max) {
    Mylib::Stack<int> s1(max); // Use my stack
    Yourlib::Stack    s2(max); // Use your stack
    // ...
}

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

void f(int max) {
    using namespace Mylib; // Make names from Mylib accessible
    Stack<int> s1(max); // Use my stack
    Yourlib::Stack s2(max); // Use your stack
    // ...
}

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

Источник: Обзор языка программирования C ++ , Бьярн Страуструп

12
19.09.2019 23:11:22
Очень интересно, что этот ответ, основанный на рекомендациях других, что Бьярн Страуструп заработал -2 ... мальчик Бьярне, должно быть, был плохим и неопытным программистом, когда он ввел эту функцию в C ++
nyholku 11.06.2015 12:48:27
@nyholku: Посмотри на это .
sbi 4.08.2015 16:01:52

Вот пример, показывающий, как using namespace std;могут возникнуть проблемы с именами:

Невозможно определить глобальную переменную в C ++

В этом примере очень общее имя алгоритма name ( std::count) конфликтует с очень разумной переменной name ( count).

2
19.09.2019 23:28:57

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

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

6
19.09.2019 23:30:12