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

Вот однострочный ряд с использованием операций apply на основе строки apply [f0]

> dat <- as.data.frame(matrix(rep(seq(4),4),ncol=2))
> colnames(dat) <- c('I','J')
> dat
   I  J
1  1  1
2  2  2
3  3  3
4  4  4
5  1  1
6  2  2
7  3  3
8  4  4
> mat <- matrix(seq(16),ncol=4)
> mat
     [,1] [,2] [,3] [,4]
[1,]    1    5    9   13
[2,]    2    6   10   14
[3,]    3    7   11   15
[4,]    4    8   12   16

> dat$K <- apply( dat, 1, function(x,mat) mat[ x[1], x[2] ], mat=mat )
> dat
  I J  K
1 1 1  1
2 2 2  6
3 3 3 11
4 4 4 16
5 1 1  1
6 2 2  6
7 3 3 11
8 4 4 16
2407
задан L. F. 29 May 2019 в 13:27
поделиться

12 ответов

Это вообще не связано с производительностью. Но учтите следующее: вы используете две библиотеки с именами 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 () не было бы событием.

2091
ответ дан 22 November 2019 в 19:51
поделиться

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

Однако вы можете свободно помещать оператор using в свои (личные) файлы * .cpp.


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

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

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

  • Объявление-использования:

     using std :: cout; // объявление-использования позволяет использовать cout без квалификации
    cout << "Значения:";
    
  • Просто набираю std ::

     std :: cout << "Values:";
    
390
ответ дан 22 November 2019 в 19:51
поделиться

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

8
ответ дан 22 November 2019 в 19:51
поделиться

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

6
ответ дан 22 November 2019 в 19:51
поделиться

Не следует использовать директиву 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)).

118
ответ дан 22 November 2019 в 19:51
поделиться

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

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

22
ответ дан 22 November 2019 в 19:51
поделиться

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

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

77
ответ дан 22 November 2019 в 19:51
поделиться
  1. Вы должны уметь читать код, написанный людьми, у которых другой стиль и мнение о передовых методах, чем у вас.

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

18
ответ дан 22 November 2019 в 19:51
поделиться

Рассмотрим

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


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

class stringstream {  // Uh oh
};

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

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

18
ответ дан 22 November 2019 в 19:51
поделиться

Другая причина - неожиданность.

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

46
ответ дан 22 November 2019 в 19:51
поделиться

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

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

28
ответ дан 22 November 2019 в 19:51
поделиться

I agree with everything Greg wrote, but I'd like to add: It can even get worse than Greg said!

Library Foo 2.0 could introduce a function, Quux(), that is an unambiguously better match for some of your calls to Quux() than the bar::Quux() your code called for years. Then your code still compiles, but it silently calls the wrong function and does god-knows-what. That's about as bad as things can get.

Keep in mind that the std namespace has tons of identifiers, many of which are very common ones (think list, sort, string, iterator, etc.) which are very likely to appear in other code, too.

If you consider this unlikely: There was a question asked here on Stack Overflow where pretty much exactly this happened (wrong function called due to omitted std:: prefix) about half a year after I gave this answer. Here is another, more recent example of such a question. Так что это настоящая проблема.


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

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


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

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


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

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


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

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


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

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


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

t find std :: достаточно болезненно, чтобы использовать директивы using даже один раз на каждые 100 kLoC, даже если это было разрешено использовать.


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

t find std :: достаточно болезненно, чтобы использовать директивы using даже один раз на каждые 100 kLoC, даже если это было разрешено использовать.


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

1332
ответ дан 22 November 2019 в 19:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: