Мне говорили, что писать код 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 import Quux()
в ваше глобальное пространство имен. Это потребует некоторых усилий для исправления, особенно если параметры функции совпадают.
Если вы использовали foo::Blah()
и bar::Quux()
, то введение foo::Quux()
было бы не-событием.
Я согласен со всем Грег написал, но я бы хотел добавить: Это может даже ухудшиться, чем сказал Грег!
Библиотека Foo 2.0 может ввести функцию Quux()
, что является однозначно лучшим соответствием для некоторых ваших вызовов Quux()
, чем bar::Quux()
, код которого вызывается в течение многих лет. Затем ваш код все еще компилируется, но он молча вызывает неправильную функцию и бог знает-что. Это примерно так же плохо, как все может быть.
Имейте в виду, что пространство имен std
содержит множество идентификаторов, многие из которых являются очень распространенными (подумайте list
, sort
, string
, iterator
и т.д.), которые, скорее всего, также отображаются в другом коде.
Если вы считаете это маловероятным: здесь был вопрос , в котором описано, как это произошло (неправильная функция, вызванная пропущенным префиксом std::
). около полугода после того, как я дал этот ответ. Здесь - еще один, более свежий пример такого вопроса.
Так что это настоящая проблема.
Здесь еще одна точка данных: много лет назад я также привык считать, что это раздражает необходимость префикса для всех из стандартной библиотеки std::
. Затем я работал в проекте, где в начале было решено, что директивы и объявления using
запрещены, за исключением областей функций. Угадай, что? Большинству из нас было очень мало недель, чтобы привыкнуть писать префикс, и через несколько недель большинство из нас даже согласилось с тем, что он действительно сделал код более удобочитаемым. Есть причина для этого: Если вам нравится более короткая или длинная проза, субъективна, но префиксы объективно добавляют ясность в код. Не только компилятор, но и вам также легче увидеть, какой идентификатор упоминается.
За десять лет этот проект вырос до нескольких миллионов строк кода. Поскольку эти обсуждения возникают снова и снова, мне некогда было любопытно, как часто в проекте использовалась (разрешенная) функция-область using
. Я нашел источники для этого и нашел только один или два десятка мест, где он использовался. Для меня это указывает на то, что, когда-то пробовали, разработчики не находят std::
достаточно болезненным, чтобы использовать директивы даже один раз каждые 100 kLoC даже там, где это разрешено использовать.
Итог: Явно префиксное все не наносит вреда, очень мало привыкает и имеет объективные преимущества. В частности, это упрощает интерпретацию кода компилятором и человеческими читателями - и это, вероятно, должно быть главной целью при написании кода.
Проблема с using namespace
в файлах заголовков ваших классов заключается в том, что это заставляет любого, кто хочет использовать ваши классы (включая файлы заголовков), также "использовать" (то есть видеть все в) эти другие пространства имен.
Тем не менее, вы можете свободно использовать оператор using в своих (приватных) *.cpp файлах.
Помните, что некоторые люди не согласны с моим высказыванием "не стесняйтесь", как это - потому что, хотя оператор использования в файле cpp лучше, чем в заголовке (потому что это не влияет на людей, которые включают ваш файл заголовка), они думают, что это все еще не хорошо (потому что в зависимости от кода это может усложнить реализацию класса). Эта тема часто задаваемых вопросов говорит,
Директива 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. Оказалось, что почти все исходные файлы имеют две строки:
using namespace std;
using namespace boost;
Многие функции Boost входят в стандарт С++ 0x, а Visual Studio 2010 имеет много С++ 0x, поэтому эти программы не компилировались.
Следовательно, избегая using namespace X;
, это форма будущей проверки, способ убедиться, что изменения в используемых библиотеках и/или заголовочных файлах не нарушают работу программы.
using
вне определения функции и редко использую using namespace
вообще.
Короткая версия: не используйте глобальное использование объявлений или директив в файлах заголовков. Не стесняйтесь использовать их в файлах реализации. Здесь, что Херб Саттер и Андрей Александреску должны сказать об этой проблеме в Стандартах кодирования С++ (смелый для моего внимания):
Резюме
Имена пространства имен предназначены для вашего удобства, а не для других: никогда не записывайте декларацию использования или директиву использования перед директивой #include.
Следствие: в заголовочных файлах не записывать уровень пространства имен с помощью директив или использования деклараций; вместо этого явно пространство имен - квалифицирует все имена. (Второе правило следует из первого, потому что заголовки никогда не могут знать, что после них может появиться другой заголовок #includes.)
Обсуждение
Вкратце: вы можете и должны использовать пространство имен с помощью деклараций и директив в ваших файлах реализации после директив #include и чувствовать себя хорошо. Несмотря на неоднократные утверждения об обратном, пространство имен, использующее декларации и директивы, не является злым, и они не преследуют цели пространств имен. Скорее, это то, что позволяет использовать пространства имен.
using
никогда не должно появляться в заголовке, я не настолько убежден в том, что свободная лицензия размещается using namespace xyz;
в любом месте вашего кода, особенно если xyz
является std
. Я использую using std::vector;
форма, поскольку это тянет только один элемент из пространства имен в псевдоглобальную область, что приводит к гораздо меньшему риску столкновения.
Нельзя использовать директиву в глобальном масштабе, особенно в заголовках. Однако есть ситуации, когда это подходит даже в файле заголовка:
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
...)
потому что он короче и имеет возможность работать с определенными пользователем типами с плавающей запятой (через зависимый от аргумента поиск).
Он считается "плохим", только когда используется глобально. Потому что:
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
была изменена, чтобы найти потенциальную перегрузку и выбрать ее.
swap
в первую очередь не так уж важно в C ++ 11, так как сам std::swap
более гибок (использует семантику перемещения). Но std::swap
автоматически выбирает ваш собственный своп, что для меня абсолютно ново (и я в это не верю).
Если вы импортируете правильные файлы заголовков, у вас внезапно появляются имена, такие как hex
, left
, plus
или count
в вашем глобальном масштабе. Это может быть удивительно, если вы не знаете, что std::
содержит эти имена. Если вы также попытаетесь использовать эти имена локально, это может привести к некоторой путанице.
Если все стандартные элементы находятся в собственном пространстве имен, вам не нужно беспокоиться о конфликтах имен с вашим кодом или другими библиотеками.
distance
. все же я предпочитаю неквалифицированные имена там, где это практически возможно, так как это повышает читабельность для меня. Кроме того, я думаю, что тот факт, что мы обычно не квалифицируем вещи в устной речи и готовы тратить время на устранение возможных двусмысленностей, означает, что имеет смысл уметь понимать то, о чем идет речь, без оговорок и применяться к источнику код, который означает, что он структурирован таким образом, что понятно, о чем идет речь, даже без квалификации.
<iomanip>
. Тем не менее, хороший момент.
Опытные программисты используют все, что решает их проблемы, и избегают любых возникающих новых проблем, и они избегают использования директив-указателей на уровне заголовка по этой точной причине.
Опытные программисты также стараются избегать полной квалификации имен внутри своих исходных файлов. Незначительная причина этого заключается в том, что не изящно писать больше кода, если недостаточно кода, если нет веских причин. Основной причиной этого является отключение зависимого от аргумента поиска (ADL).
Каковы эти веские причины? Иногда программисты явно хотят отключить ADL, в других случаях они хотят устранить неоднозначность.
Итак, все в порядке:
Я согласен, что его нельзя использовать глобально, но не так зло использовать локально, как в namespace
. Вот пример из "Язык программирования С++":
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
).
Еще одна причина - сюрприз.
Если я вижу cout << blah
вместо std::cout << blah
Я думаю, что это за cout
? Это нормальный cout
? Это что-то особенное?
cout
- плохой пример, потому что все это признают. Но представьте себе future
в финансовом приложении. Это контракт на покупку или продажу чего-либо на указанную дату? Нет, это не так. Если бы в коде говорилось о std::future
вас не так легко спутать.
Я также считаю это плохой практикой. Зачем? Только однажды я подумал, что функция пространства имен - это разделить материал, чтобы я не портил его, выбросив все в одну глобальную сумку.
Однако, если я часто использую "cout" и "cin", я пишу: using std::cout; using std::cin;
в файле cpp (никогда в файле заголовка, поскольку он распространяется с помощью #include
). Я думаю, что noone sane никогда не назовет поток 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:: повсюду более трудно читать (больше текста и всего этого).
Лошади для курсов - управляйте своей сложностью, как вы можете и можете себя чувствовать.
Использование многих пространств имен в то же время является, по-видимому, рецептом для катастрофы, но использование JUST namespace std
и только пространство имен std
, по моему мнению, не является большой сделкой, потому что переопределение может происходить только по вашему собственному коду...
Поэтому просто рассматривайте их как зарезервированные имена, такие как "int" или "class", и это все.
Люди должны перестать быть такими анальными. Ваш учитель был прав все время. Просто используйте ОДИН пространство имен; в этом весь смысл использования пространств имен на первом месте. Вы не должны использовать более одного одновременно. Если это не ваше. Так что повторное переопределение не произойдет.
min
, end
и less
появляются в пространстве имен std::
. Более того, теперь, когда в std::
есть тысячи символов, читателю полезно знать, откуда появился новый символ, который они могут не знать.
вам нужно уметь читать код, написанный людьми, которые имеют разные мнения о стиле и лучшей практике, чем вы.
Если вы используете cout, никто не смущается. Но когда у вас много пространств имен, которые летают, и вы видите этот класс, и вы не совсем уверены, что он делает, поскольку явное пространство имен действует как комментарий рода. Вы можете видеть на первый взгляд: "О, это операция с файловой системой" или "Что делает сетевые вещи".
Рассмотрим
// myHeader.h
#include <sstream>
using namespace std;
// someoneElses.cpp/h
#include "myHeader.h"
class stringstream { // uh oh
};
Обратите внимание, что это простой пример, если у вас есть файлы с 20 включенными и другими импортами, у вас будет много зависимостей, чтобы разобраться в проблеме. Хуже всего то, что вы можете получить несвязанные ошибки в других модулях в зависимости от определений, которые конфликтуют.
Это не ужасно, но вы избавитесь от головных болей, не используя его в файлах заголовков или в глобальном пространстве имен. Скорее всего, это можно сделать в очень ограниченных областях, но у меня никогда не было проблемы с вводом дополнительных 5 символов, чтобы выяснить, откуда мои функции.
Конкретный пример для разъяснения проблемы. Представьте, что у вас есть ситуация, когда у вас есть 2 библиотеки, foo и bar, каждая с собственным пространством имен:
namespace foo {
void a(float) { /* does something */ }
}
namespace bar {
...
}
Теперь скажем, вы используете foo и bar вместе в своей собственной программе следующим образом:
using namespace foo;
using namespace bar;
void main() {
a(42);
}
В этот момент все в порядке. Когда вы запускаете свою программу, она "делает что-то". Но позже вы обновляете панель и говорите, что она изменилась так:
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)
}
Итак, вам нужно будет провести некоторое техническое обслуживание, чтобы уточнить, что означало "a" (т.е. foo::a
). Это, вероятно, нежелательно, но, к счастью, это довольно просто (просто добавьте foo::
перед всеми вызовами a
, которые компилятор отмечает как неоднозначный).
Но представьте себе альтернативный сценарий, в котором вместо этого вместо этого изменился бар, чтобы выглядеть следующим образом:
namespace bar {
void a(int) { /* does something completely different */ }
}
В этот момент ваш вызов a(42)
внезапно привязывается к bar::a
вместо foo::a
и вместо того, чтобы делать что-то, он делает что-то совершенно другое. Никакого предупреждения компилятора или чего-либо еще. Ваша программа просто начинает делать что-то совершенно иное, чем раньше.
Когда вы используете пространство имен, вы рискуете подобным сценарием, поэтому людям неудобно использовать пространства имен. Чем больше вещей в пространстве имен, тем больше риск конфликта, поэтому людям может быть еще более неудобно использование пространства имен std (из-за количества вещей в этом пространстве имен), чем другие пространства имен.
В конечном счете это компромисс между возможностью записи и надежностью/ремонтопригодностью. Читаемость также может иметь значение, но я могу видеть аргументы для этого в любом случае. Обычно я бы сказал, что надежность и ремонтопригодность важнее, но в этом случае вы будете постоянно оплачивать затраты на запись для довольно редкой надежности/ремонтопригодности. "Лучший" компромисс будет определять ваш проект и ваши приоритеты.
Пространство имен является именованной областью. Пространства имен используются для группировки связанных деклараций и сохранения отдельных предметы раздельные. Например, две отдельно разработанные библиотеки могут использовать одно и то же имя для обозначения разных но пользователь может использовать оба:
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
/ / ...
}
Пространства имен предоставляют мощный инструмент для управления различными библиотеками и различными версиями код. В частности, они предлагают альтернативу программиста того, как явным становится ссылка на нелокальную имя.
Источник: обзор языка программирования С++ by Bjarne Stroustrup
Я согласен с остальными здесь, но хотел бы затронуть проблемы, связанные с удобочитаемостью - вы можете избежать всего этого, просто используя 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;
}
Пример, в котором использование пространства имен std вызывает ошибку компиляции из-за неоднозначности подсчета, которая также является функцией в библиотеке алгоритмов.
#include <iostream>
using namespace std;
int count = 1;
int main() {
cout<<count<<endl;
}
::count
проблема решена. Обычно из пространства имен std у вас будет больше информации, чем из других мест, поэтому сохранение директивы using namespace может спасти вам ввод текста.
Я не думаю, что это обязательно плохая практика при любых условиях, но вам нужно быть осторожным, когда вы ее используете. Если вы пишете библиотеку, вы, вероятно, должны использовать операторы разрешения области видимости с пространством имен, чтобы ваша библиотека не загоняла головы другим библиотекам. Для кода уровня приложения я не вижу в этом ничего плохого.
Это не ухудшает работу вашего программного обеспечения или проекта, включение пространства имен в начале исходного кода не так уж плохо. Включение инструкции using namespace std
с using namespace std
зависит от ваших потребностей и того, как вы разрабатываете программное обеспечение или проект.
Пространство namespace std
содержит стандартные функции и переменные C++. Это пространство имен полезно, когда вы часто используете стандартные функции C++.
Как упоминается на этой странице:
Утверждение, использующее пространство имен std, обычно считается плохой практикой. Альтернативой этому утверждению является указание пространства имен, к которому принадлежит идентификатор, с помощью оператора области (: :) каждый раз, когда мы объявляем тип.
И посмотрите это мнение:
Нет проблем с использованием "использования пространства имен std" в исходном файле при интенсивном использовании пространства имен и точно знать, что ничего не столкнется.
Некоторые люди говорили, что это плохая практика включать using namespace std
в исходные файлы, потому что вы вызываете из этого пространства имен все функции и переменные. Если вы хотите определить новую функцию с тем же именем, что и другая функция, содержащаяся в namespace std
вы должны перегрузить функцию, и это может вызвать проблемы из-за компиляции или выполнения. Он не будет компилироваться или исполняться, как вы ожидаете.
Как упоминается на этой странице:
Хотя утверждение не позволяет нам печатать std :: всякий раз, когда мы хотим получить доступ к классу или типу, определенному в пространстве имен std, он импортирует всю полноту пространства имен std в текущее пространство имен программы. Давайте рассмотрим несколько примеров, чтобы понять, почему это может быть не так хорошо
...
Теперь на более позднем этапе разработки мы хотим использовать другую версию cout, которая реализована в некоторой библиотеке под названием "foo" (например)
...
Обратите внимание на то, что существует двусмысленность, на которую указывает точка cout. Компилятор может обнаружить это, а не компилировать программу. В худшем случае программа все еще может компилироваться, но вызывает неправильную функцию, поскольку мы никогда не указывали, к какому пространству имен принадлежал идентификатор.
Это плохая практика, часто называемая глобальным загрязнением пространства имен. Проблемы могут возникать, когда более одного пространства имен имеет одно и то же имя функции с сигнатурой, тогда компилятор будет неоднозначным, чтобы решить, какой из них вызывать, и этого можно избежать, когда вы указываете пространство имен с помощью вызова функции, например std::cout
, Надеюсь это поможет.:)
Я согласен с другими - он спрашивает о столкновениях имен, двусмысленностях, а затем тот факт, что он менее явный. Хотя я вижу использование using
, мое личное предпочтение - ограничить его. Я также решительно рассмотрю то, что некоторые другие отметили:
Если вы хотите найти имя функции, которое может быть довольно распространенным именем, но вы хотите только найти его в пространстве имен std
(или наоборот - вы хотите изменить все вызовы, которые НЕ находятся в пространстве имен std
, namespace X
,...), то как вы предлагаете это сделать? Вы могли бы написать программу для этого, но не лучше ли тратить время на работу над самим проектом, а не на создание программы для поддержки вашего проекта?
Лично я на самом деле не против std::
prefix. Мне нравится выглядеть больше, чем не иметь его. Я не знаю, потому что это явное и говорит мне: "Это не мой код... я использую стандартную библиотеку", или если это что-то еще, но я думаю, что это выглядит лучше. Это может быть странно, учитывая, что я только недавно попал в 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;
}
Я не буду спорить о том, плохая идея или нет. Тем не менее я утверждаю, что он сохраняет чистоту для моего проекта и в то же время делает его конкретным: True. Мне нужно использовать Boost, но я использую его, как будто libstd C++ в конечном итоге получит его. Да, начинать свой собственный проект и начинать со стандартного (...) в самом начале очень долгий путь, помогая обслуживанию, развитию и всему, что связано с проектом!
Редактировать:
Теперь, когда у меня есть время, просто что-то прояснить. На самом деле я не считаю целесообразным использовать имя класса/любого в STL намеренно и, более конкретно, вместо. Строка - это исключение (игнорируйте первый, выше или второй здесь, каламбур, если вы должны) для меня, поскольку мне не понравилась идея "String". Как бы то ни было, я все еще очень склонен к C и предвзято относился к C++. Сохраняя детали, многое из того, что я работаю, больше подходит для C (но это было хорошее упражнение и хороший способ сделать себя). Изучите другой язык и b. Попробуйте не быть менее предвзятым против объекта/классов /etc, который, возможно, как менее замкнутый, менее высокомерный, более приемный.). Но полезно то, что некоторые из них уже предлагали: я действительно использую список (он довольно общий, не так ли?), Сортировать (то же самое), чтобы называть два, которые вызовут столкновение имен, если я буду делать using namespace std;
и поэтому с этой целью я предпочитаю быть конкретным, контролировать и знать, что, если я намереваюсь, чтобы это было стандартное использование, мне придется его указать. Проще говоря: не допускается.
А что касается создания регулярного выражения Boost std
. Я делаю это для будущей интеграции, и, опять же, я полностью признаю, что это предвзятость - я не думаю, что это так же уродливо, как boost::regex::...
Для меня это другое дело. В C++ есть много вещей, которые я до сих пор еще не получил, чтобы полностью согласиться на внешний вид и методы (еще один пример: вариативные шаблоны против var args [хотя я допускаю, что вариативные шаблоны очень полезны!]). Даже те, что я принимаю, это было трудно, и у меня все еще есть проблемы с ними.
std
является неопределенным поведением и поэтому никогда не должно выполняться.
"Почему" using namespace std; "считается плохой практикой в С++?"
Я сказал так: почему набирать 5 дополнительных символов считается громоздким некоторыми?
Рассмотрим, например, написав кусок численного программного обеспечения, почему бы мне даже подумать о загрязнении моего глобального пространства имен, сократив общий "std::vector" до "vector", когда "вектор" является одной из проблемных областей наиболее важных понятий?
Это зависит от того, где он находится. Если это общий заголовок, вы уменьшаете значение пространства имен, объединяя его в глобальное пространство имен. Имейте в виду, что это может быть аккуратный способ создания глобальных модулей.
Из моего опыта, если у вас есть несколько библиотек, которые используют, скажем, cout
, но для другой цели вы можете использовать неправильный cout
.
Например, если я набираю using namespace std;
и using namespace otherlib;
и набираю только cout (что бывает в обоих), а не std::cout
(или 'otherlib::cout'
), вы можете использовать неправильный, и получить ошибки, гораздо эффективнее и эффективнее использовать std::cout
.
Чтобы ответить на ваш вопрос, я смотрю на это так: практически все программисты (не все) вызывают пространство имен std. Поэтому нужно привыкнуть НЕ использовать вещи, которые сталкиваются или используют те же имена, что и в пространстве имен std. Это очень много, но не столько по сравнению с количеством возможных когерентных слов и псевдонимов, которые могут быть придуманы строго.
Я имею в виду действительно... говоря "не полагайтесь на это присутствующее", просто заставляет вас полагаться на него, не присутствуя. У вас постоянно возникают проблемы с заимствованием фрагментов кода и их постоянным ремонтом. Просто держите свой пользовательский и заимствованный материал в ограниченном объеме, как и должно быть, и быть ОЧЕНЬ щадящим с глобальными (честно глобалы должны почти всегда быть последним средством для целей "компиляции сейчас, здравомыслия позже" ). По-моему, это плохой совет от вашего учителя, потому что использование std будет работать как для "cout", так и для "std:: cout", но НЕ использовать std будет работать только для "std:: cout". Вы не всегда будете достаточно удачливы, чтобы написать свой собственный код.
ПРИМЕЧАНИЕ. Не сосредотачивайтесь слишком много на проблемах эффективности, пока вы не узнаете немного о том, как работают компиляторы. С небольшим опытом кодирования вам не нужно много узнавать о них, прежде чем вы поймете, насколько они могут обобщить хороший код во что-то простое. Каждый бит такой же простой, как если бы вы написали все это в C. Хороший код настолько сложный, насколько он должен быть.
<algorithm>
), кажется немного натянутой мысль, что одни и те же люди могут надежно избегать этих идентификаторов. Посмотрите свой собственный код и скажите, что у вас никогда нет переменной или функции с именем count
. Или distance
, или log
, destroy
, launch
, visit
, beta
, sample
, messages
, clamp
, erase
, copy
, modulus
, left
и т. Д. Не говоря уже о всех идентификаторах, которые еще не в std
которые будут нарушать ваш код, когда C ++ 35 выходит...
С неквалифицированными импортированными идентификаторами вам нужны внешние инструменты поиска, такие как grep, чтобы узнать, где объявляются идентификаторы. Это затрудняет обоснование корректности программы.
Да, пространство имен важно. Однажды в моем проекте мне нужно было импортировать одно объявление var в исходный код, но при компиляции он противоречил другой сторонней библиотеке.
В конце концов, мне пришлось обходить его другими средствами и сделать код менее понятным.
Вот пример, показывающий, как using namespace std;
может вызвать проблемы с конфликтом имен:
Невозможно определить глобальную переменную в С++
В примере очень общее имя имени алгоритма (std::count
) сталкивается с очень разумным именем переменной (count
).
Я думаю, что использование локально или глобально должно зависеть от приложения.
Поскольку, когда мы используем библиотеку локально, иногда код становится настоящим беспорядком. Читаемость будет низкой.
поэтому мы должны использовать библиотеки локально, только когда есть возможность конфликтов.
Я больше не переживаю человека. Итак, дайте мне знать, если я ошибаюсь.
Честно говоря, для меня это как обсуждение количества пробелов для отступов. Использование директив в заголовках может привести к повреждению. Но в файлах c++? Возможно, если вы используете сразу 2 пространства имен. Но если вы используете один, это больше о стиле, чем реальной эффективности. Знаете ли вы, почему темы об углублении настолько популярны? Любой может сказать что-то об этом и звучать очень умный и опытный.
Здесь точка зрения, которую я не нашел ни в одном из других ответов: используйте только одно пространство имен. Основная причина того, почему пространства имен плохие, по большинству ответов, заключается в том, что у вас могут быть конфликтующие имена функций, которые могут привести к полному беспорядку. Однако это не произойдет, если вы используете только одно пространство имен. Определите, в какой библиотеке вы будете использовать наиболее (возможно, using namespace std;
) и придерживайтесь его.
Можно считать, что он имеет невидимый префикс библиотеки - std::vector
становится просто vector
. Это, на мой взгляд, лучшее из обоих миров: с одной стороны, это уменьшает объем ввода, который вы должны делать (как это предусмотрено пространствами имен), а с другой - для по-прежнему требуется использовать префиксы для ясности и безопасности. Если есть функция или объект без префикса пространства имен - вы знаете это из одного указанного вами пространства имен.
Просто помните, что если вы решите использовать один глобально - не используйте других локально. Это возвращается к другим ответам, что локальные пространства имен часто более полезны, чем глобальные, поскольку они обеспечивают разнообразие в удобстве.
Существует несколько причин, которые включают в себя пространство имен std, как плохую практику. По существу, это сводится к следующим основным моментам: