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

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

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

 

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

```
using namespace foo;
using namespace bar;

```

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

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



Я согласен со всем [Грег написал](/questions/618/why-is-using-namespace-std-considered-bad-practice/9715#9715), но я бы хотел добавить:  **Это может даже ухудшиться, чем сказал Грег!**

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

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

Если вы считаете это маловероятным: здесь был вопрос , в котором описано, как это произошло (неправильная функция, вызванная пропущенным префиксом `std::`). около полугода после того, как я дал этот ответ. [Здесь](/questions/10051/confusion-about-pointers-and-references-in-c) - еще один, более свежий пример такого вопроса.
Так что это настоящая проблема.

---

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

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

---

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

 

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

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

 

---

 Помните, что некоторые люди не согласны с моим высказыванием "не стесняйтесь", как это - потому что, хотя оператор использования в файле cpp лучше, чем в заголовке (потому что это не влияет на людей, которые включают ваш файл заголовка), они думают, что это все еще не хорошо (потому что в зависимости от кода это может усложнить реализацию класса). [Эта тема часто задаваемых вопросов](https://isocpp.org/wiki/faq/coding-standards#using-namespace-std%23using-namespace-std) говорит,

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

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

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

 
```
using std::cout; // a using-declaration lets you use cout without qualification
cout << "Values:";

```
* Просто наберите std ::

 
```
std::cout << "Values:";

```

 

Недавно я столкнулся с жалобой на [Visual Studio 2010](https://en.wikipedia.org/wiki/Microsoft_Visual_Studio#Visual_Studio_2010). Оказалось, что почти все исходные файлы имеют две строки:

```
using namespace std;
using namespace boost;

```

Многие функции [Boost](https://en.wikipedia.org/wiki/Boost_%28C%2B%2B_libraries%29) входят в стандарт С++ 0x, а Visual Studio 2010 имеет много С++ 0x, поэтому эти программы не компилировались.

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

 

Короткая версия: не используйте глобальные объявления `using` или директивы в заголовочных файлах. Не стесняйтесь использовать их в файлах реализации. Вот что [Херб Саттер](https://en.wikipedia.org/wiki/Herb_Sutter) и [Андрей Александреску](https://en.wikipedia.org/wiki/Andrei_Alexandrescu) должны сказать об этой проблеме в [C++ Стандарты кодирования](https://rads.stackoverflow.com/amzn/click/com/0321113586) (жирный шрифт для акцента - мое):

> 
> 
> Резюме
> -------
> 
> 
>  Использование пространства имен для вашего удобства, а не для вас, чтобы навязывать другим: никогда не пишите объявление использования или директиву использования перед директивой #include.
> 
> 
>  Следствие: в заголовочных файлах не пишите на уровне пространства имен, используя директивы или объявления; вместо этого явно определите пространство имен для всех имен. (Второе правило следует из первого, потому что заголовки никогда не могут знать, какие другие заголовки #include могут появиться после них.)
> 
> 
>  Обсуждение
> -----------
> 
> 
>  Вкратце: вы можете и должны использовать пространство имен, используя объявления и директивы свободно в ваших файлах реализации после директив #include, и вам это нравится. **Несмотря на неоднократные утверждения об обратном, пространства имен, использующие декларации и директивы, не являются злом и не наносят ущерба цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования**.
> 
> 
> 



Не следует использовать директиву `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`...), потому что она короче и способна работать с определенными пользователем типами с плавающей запятой (через [поиск, зависящий от аргумента](https://en.wikipedia.org/wiki/Argument-dependent_name_lookup) (ADL)).



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

Он считается "плохим", только когда  **используется глобально**. Потому что:

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

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

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

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

В С++ 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::swap` для `value_`, т.е. `void std::swap(int, int)`.
* Если у вас есть перегрузка `void swap(Child&, Child&)` реализована, компилятор выберет ее.
* Если у вас нет этой перегрузки, компилятор будет использовать `void std::swap(Child&,Child&)` и попытаться наилучшим образом заменить их.

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

 

Если вы импортируете правильные файлы заголовков, у вас внезапно появляются имена, такие как [`hex`](http://en.cppreference.com/w/cpp/io/manip/hex), [`left`](http://en.cppreference.com/w/cpp/io/manip/left), [`plus`](http://en.cppreference.com/w/cpp/utility/functional/plus) или [`count`](http://en.cppreference.com/w/cpp/algorithm/count) в вашем глобальном масштабе. Это может быть удивительно, если вы не знаете, что `std::` содержит эти имена. Если вы также попытаетесь использовать эти имена локально, это может привести к некоторой путанице.

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

 

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

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

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

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

* Использование-директив на уровне функций и использование-деклараций внутри реализации функций
* Использование-объявления уровня исходного файла в исходных файлах
* (Иногда) с использованием-директив на уровне исходного файла

 

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

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



Я согласен с тем, что его не следует использовать глобально, но использовать его локально не так плохо, как в `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

}

```

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

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



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

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



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

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

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

 

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

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

 

Рассмотрим

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

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

class stringstream {  // Uh oh
};

```

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

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



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



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

Поэтому просто рассматривайте их как зарезервированные имена, такие как "int" или "class", и это все.

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

 

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

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

```
// 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;
}

```
 

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

```
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++
Бьярн Страуструп



Конкретный пример, чтобы прояснить проблему. Представьте, что у вас есть ситуация, когда у вас есть две библиотеки, `foo` и `bar`, каждая со своим собственным пространством имен:

```
namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

```

Теперь предположим, что вы используете `foo` и `bar` вместе в своей собственной программе следующим образом:

```
using namespace foo;
using namespace bar;

void main() {
    a(42);
}

```

На данный момент все в порядке. Когда вы запускаете свою программу, она "что-то делает". Но позже вы обновите `bar` и допустим, что оно изменилось так:

```
namespace bar {
    void a(float) { /* Does something completely different */ }
}

```

На этом этапе вы получите ошибку компилятора:

```
using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

```

Таким образом, вам нужно будет провести некоторое обслуживание, чтобы уточнить, что означает "а" `foo::a`. Это нежелательно, но, к счастью, это довольно просто (просто добавьте `foo::` перед всеми вызовами `a`, которые компилятор помечает как неоднозначные).

Но представьте альтернативный сценарий, в котором вместо этого изменился бар:

```
namespace bar {
    void a(int) { /* Does something completely different */ }
}

```

В этот момент ваш вызов `a(42)` неожиданно связывается с `bar::a` вместо `foo::a`, и вместо того, чтобы "что-то" делать, он делает "что-то совершенно другое". Нет предупреждения компилятора или что-нибудь. Ваша программа просто начинает что-то совершенно другое, чем раньше.

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

В конечном итоге это компромисс между возможностью записи и надежностью/ремонтопригодностью. Читаемость может также учитывать, но я мог видеть аргументы для этого в любом случае. Обычно я бы сказал, что надежность и ремонтопригодность важнее, но в этом случае вы будете постоянно оплачивать стоимость записи за довольно редкое влияние надежности/ремонтопригодности. "Лучший" компромисс будет определять ваш проект и ваши приоритеты.



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

```
#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}

```
 

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

 

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

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

> 
> Как указано на этой [странице](https://www.geeksforgeeks.org/using-namespace-std-considered-bad-practice/):
> 
> 
>  Утверждение, использующее пространство имен std, обычно считается плохим практика. Альтернативой этому утверждению является указание пространство имен, к которому относится идентификатор, с помощью оператора области действия (: :) каждый раз, когда мы объявляем тип.
> 
>  And see [this opinion](https://www.sololearn.com/Discuss/187690/is-using-namespace-std-a-bad-practice/):
> 
>  Нет проблем с использованием "using namespace std" в вашем исходном файле когда вы интенсивно используете пространство имен и точно знаете, что ничто не столкнется.
> 
> 
> 

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

> 
> Как указано на этой [странице](https://www.geeksforgeeks.org/using-namespace-std-considered-bad-practice/):
> 
> 
>  Хотя это утверждение спасает нас от ввода std::всякий раз мы хотим получить доступ к классу или типу, определенному в пространстве имен std, это импортирует все пространство имен std в текущее пространство имен программы. Давайте возьмем несколько примеров, чтобы понять, почему это может быть, не такая хорошая вещь
> 
>  ...
> 
>  Теперь на более поздней стадии разработки мы хотим использовать другую версию Cout, который специально реализован в некоторой библиотеке под названием 'Foo' (для пример)
> 
>  ...
> 
>  Обратите внимание на неопределенность, на какую библиотеку указывает cout? Компилятор может обнаружить это и не скомпилировать программу. В худшем В этом случае программа может все еще скомпилироваться, но вызвать неправильную функцию, так как мы никогда не указывали, к какому пространству имен принадлежит идентификатор.
> 
> 
> 



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

 

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

 

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

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

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



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

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

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

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

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

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

Так вот как я это решил. Установите Boost regex и свяжите его. Затем я делаю следующее, чтобы, когда libstd C++ полностью его реализовал, мне нужно было только удалить этот блок, а код остался прежним:

```
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, но я использую его так, как в итоге у libstd C++. Да, начинать собственный проект и начинать со стандартного (...) в самом начале очень важно, помогая в обслуживании, разработке и всем, что связано с проектом!

Просто чтобы прояснить кое-что: на самом деле я не думаю, что будет хорошей идеей использовать имя класса/что угодно в [STL](https://en.wikipedia.org/wiki/Standard_Template_Library) намеренно и более конкретно вместо. Строка является исключением (игнорируйте первое, выше или второе здесь, каламбур, если нужно) для меня, поскольку мне не понравилась идея "String".

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

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



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

 

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

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

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

 

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

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