“使用命名空间std;&quot”的问题是什么?
我已经听到使用命名空间std;
是错误的,并且我应该使用std :: cout
和std :: cin cin
直接而代替。
为什么这是?它是否会宣布与std
名称空间中的内容相同名称的变量?有绩效影响吗?
I have heard using namespace std;
is wrong, and that I should use std::cout
and std::cin
directly instead.
Why is this? Does it risk declaring variables that share the same name as something in the std
namespace? Are there performance implications?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
您需要能够读取与您不同的风格和最佳实践意见的人所写的代码。
如果您仅使用
cout
,没有人会感到困惑。但是,当您有很多名称空间,您会看到此类班级,而您不确定它的作用时,将命名空间显式充当各种评论。乍一看,您可以看到“哦,这是一个文件系统操作”或“在做网络工作”。You need to be able to read code written by people who have different style and best practices opinions than you.
If you're only using
cout
, nobody gets confused. But when you have lots of namespaces flying around and you see this class and you aren't exactly sure what it does, having the namespace explicit acts as a comment of sorts. You can see at first glance, "oh, this is a filesystem operation" or "that's doing network stuff".同时使用许多名称空间显然是灾难的秘诀,但是仅使用命名空间
std
,而名称空间std
在我看来并不是什么大事,因为重新定义可以重新定义仅通过您自己的代码出现...因此,只需将它们视为保留名称,例如“ int”或“ class”,仅此而已。
人们应该停止对此感到肛门。您的老师一直是对的。只需使用一个名称空间;这是首先使用名称空间的重点。您不应该同时使用多个。除非它是你自己的。因此,重新定义不会发生。
Using many namespaces at the same time is obviously a recipe for disaster, but using JUST namespace
std
and only namespacestd
is not that big of a deal in my opinion because redefinition can only occur by your own code...So just consider them functions as reserved names like "int" or "class" and that is it.
People should stop being so anal about it. Your teacher was right all along. Just use ONE namespace; that is the whole point of using namespaces the first place. You are not supposed to use more than one at the same time. Unless it is your own. So again, redefinition will not happen.
我同意这里的其他人,但是我想解决有关可读性的担忧 - 您可以通过简单地使用文件,功能或类声明的顶部的Typedef来避免所有这些问题。
我通常在课堂声明中将其用作类中的方法倾向于处理类似的数据类型(成员),而Typedef是一个机会,可以分配在类上下文中有意义的名称。这实际上有助于类方法的定义可读性。
在实施中:
与:或:
或:
I agree with the others here, but I would like to address the concerns regarding readability - you can avoid all of that by simply using typedefs at the top of your file, function or class declaration.
I usually use it in my class declaration as methods in a class tend to deal with similar data types (the members) and a typedef is an opportunity to assign a name that is meaningful in the context of the class. This actually aids readability in the definitions of the class methods.
and in the implementation:
as opposed to:
or:
名称空间是命名范围。名称空间用于分组相关声明并保持分开
项目分开。例如,两个单独开发的库可能会使用相同的名称来参考不同的
项目,但是用户仍然可以同时使用:
重复名称名称对读者和作家都可以分散注意力。因此,有可能
指出从特定命名空间中的名称可用,而无需明确的资格。例如:
名称空间为管理不同库和不同版本的代码提供了强大的工具。特别是,他们提供了程序员的替代方案,以表明如何提及非本地名称。
来源: C ++编程语言的概述
由Bjarne Stroustrup
A namespace is a named scope. Namespaces are used to group related declarations and to keep separate
items separate. For example, two separately developed libraries may use the same name to refer to different
items, but a user can still use both:
Repeating a namespace name can be a distraction for both readers and writers. Consequently, it is possible
to state that names from a particular namespace are available without explicit qualification. For example:
Namespaces provide a powerful tool for the management of different libraries and of different versions of code. In particular, they offer the programmer alternatives of how explicit to make a reference to a nonlocal name.
Source: An Overview of the C++ Programming Language
by Bjarne Stroustrup
其中
使用命名空间std
的一个示例由于计数的歧义而引发了汇编错误,这也是算法库中的函数。An example where
using namespace std
throws a compilation error because of the ambiguity of count, which is also a function in algorithm library.这是情况下的情况。我们希望最大程度地减少该软件在其寿命中的“总拥有成本”。说“使用命名空间std”有一定的成本,但是 使用它也具有可读性的成本。
人们正确地指出,当使用标准库引入新的符号和定义时,您的代码将停止编译,并且您可能被迫重命名变量。但是,这可能是长期的,因为如果您将关键字用于某些令人惊讶的目的,将来的维护者将暂时混淆或分心。
您不希望 拥有一个称为向量的模板,例如,这不是其他所有人都知道的向量。并且在C ++库中如此引入的新定义数量很小,可能根本不会出现。 是必须进行这种更改的成本,但是成本不是很高,并且由于不使用
std
符号而获得的清晰度所抵消,以抵消。鉴于类,变量和功能的数量,说明
std ::
在每个人的代码上可能会增加50%,并使您的头部更加困难。现在,可以在一个屏幕上使用的算法或逐步使用一个屏幕代码,需要来回滚动才能遵循。这是一个真正的成本。可以说,这可能不是很高的成本,但是否认它的人甚至没有经验,教条或简直是错误的。我将提供以下规则:
std
与所有其他库不同。这是每个人基本上都需要知道的一个库,我认为最好将其视为语言的一部分。一般而言,即使没有其他库切勿通过在标题中使用将此放入编译单元(.cpp文件)的作者(.cpp文件)。 始终将决定推迟给编译单元作者。即使在一个决定使用
使用命名空间std
的项目中,到处都可以填补一些最佳将作为该规则例外的模块。即使命名空间功能使您拥有许多具有相同符号的模块,但这样做会感到困惑。在可能的程度上保持名称不同。即使不使用命名空间功能,如果您的类名为
foo
和std
引入了名为foo
的类无论如何,要重命名您的课程。使用名称空间的一种替代方法是通过将其前缀前缀来手动命名空间符号。实际上,我有两个我使用的库,这些库是从C库开始的,其中每个符号都带有“ AK”或“ SCWIN”。一般来说,这就像避免使用“使用”构造,但您不写双结肠。
ak :: foo()
是akfoo()
。它使代码使代码5-10%浓密且详细,唯一的缺点是,如果您必须使用两个具有相同前缀的库,那么您会遇到大麻烦。请注意,X窗口库在这方面非常出色,除了它们忘了使用一些#Defines这样做:True and False应该是Xtrue和Xfalse,并且与Sybase或Oracle建立了同样使用的Sybase或Oracle的命名空间冲突有不同的值! (在数据库的情况下ASCII 0和1!)这样的一个特殊优势是,它似乎不适用于预处理器定义,而C ++使用
//
namespace namespace
system do do do d'' T处理它们。一个很好的好处是,它从成为项目的一部分到最终成为图书馆的有机斜率。在我的大型应用中,所有窗口类都均为win
,所有信号处理模块mod等等。将其中的任何一个重复使用的可能性很小,因此将每个组进入图书馆没有实际好处,但是在几秒钟内,该项目如何分解为子项目。It's case by case. We want to minimize the "total cost of ownership" of the software over its lifespan. Stating "using namespace std" has some costs, but not using it also has a cost in legibility.
People correctly point out that when using it, when the standard library introduces new symbols and definitions, your code ceases to compile, and you may be forced to rename variables. And yet this is probably good long-term, since future maintainers will be momentarily confused or distracted if you're using a keyword for some surprising purpose.
You don't want to have a template called vector, say, which isn't the vector known by everyone else. And the number of new definitions thus introduced in the C++ library is small enough it may simply not come up. There is a cost to having to do this kind of change, but the cost is not high and is offset by the clarity gained by not using
std
symbol names for other purposes.Given the number of classes, variables, and functions, stating
std::
on every one might fluff up your code by 50% and make it harder to get your head around. An algorithm or step in a method that could be taken in on one screenful of code now requires scrolling back and forth to follow. This is a real cost. Arguably it may not be a high cost, but people who deny it even exists are inexperienced, dogmatic, or simply wrong.I'd offer the following rules:
std
is different from all other libraries. It is the one library everyone basically needs to know, and in my view is best thought of as part of the language. Generally speaking there is an excellent case forusing namespace std
even if there isn't for other libraries.Never force the decision onto the author of a compilation unit (a .cpp file) by putting this
using
in a header. Always defer the decision to the compilation unit author. Even in a project that has decided to useusing namespace std
everywhere may fine a few modules that are best handled as exceptions to that rule.Even though the namespace feature lets you have many modules with symbols defined the same, it's going to be confusing to do so. Keep the names different to the extent possible. Even if not using the namespace feature, if you have a class named
foo
andstd
introduces a class namedfoo
, it's probably better long-run to rename your class anyway.An alternative to using namespaces is to manually namespace symbols by prefixing them. I have two libraries I've used for decades, both starting as C libraries, actually, where every symbol is prefixed with "AK" or "SCWin". Generally speaking, this is like avoiding the "using" construct, but you don't write the twin colons.
AK::foo()
is insteadAKFoo()
. It makes code 5-10% denser and less verbose, and the only downside is that you'll be in big trouble if you have to use two such libraries that have the same prefixing. Note the X Window libraries are excellent in this regard, except they forgot to do so with a few #defines: TRUE and FALSE should have been XTRUE and XFALSE, and this set up a namespace clash with Sybase or Oracle that likewise used TRUE and FALSE with different values! (ASCII 0 and 1 in the case of the database!) One special advantage of this is that it applies seemlessly to preprocessor definitions, whereas the C++using
/namespace
system doesn't handle them. A nice benefit of this is that it gives an organic slope from being part of a project to eventually being a library. In a large application of mine, all window classes are prefixedWin
, all signal-processing modules Mod, and so on. There's little chance of any of these being reused so there's no practical benefit to making each group into a library, but it makes obvious in a few seconds how the project breaks into sub-projects.它不会使您的软件或项目性能更糟。源代码开头的名称空间不错。使用名称空间STD 指令包含
根据您的需求以及您开发软件或项目的方式而有所不同。
名称空间std
包含C ++标准功能和变量。当您经常使用C ++标准功能时,此名称空间很有用。有人说过,在源文件中使用名称空间std 包括
是一个不好的做法,因为您正在从该命名空间中调用所有函数和变量。当您想定义具有与
名称空间std
中包含的另一个函数相同名称的新功能时,您会超载该功能,并且由于编译或执行而可能会产生问题。它不会按照您的期望进行编译或执行。It doesn't make your software or project performance worse. The inclusion of the namespace at the beginning of your source code isn't bad. The inclusion of the
using namespace std
instruction varies according to your needs and the way you are developing the software or project.The
namespace std
contains the C++ standard functions and variables. This namespace is useful when you often would use the C++ standard functions.Some people had said that is a bad practice to include the
using namespace std
in your source files because you're invoking from that namespace all the functions and variables. When you would like to define a new function with the same name as another function contained in thenamespace std
you would overload the function and it could produce problems due to compile or execute. It will not compile or executing as you expect.我同意别人的观点 - 它要求姓名冲突,歧义,然后事实是它不太明确。虽然我可以看到
使用
的使用,但我的个人喜好是限制它。我还将强烈考虑其他一些人指出的:如果您想找到一个可能是相当通用名称的函数名称,但是您只想在
std
sand> namespace(或反向 - 反向 -您想更改名称空间中的所有 std ,namespacex
...)的调用,然后您如何建议这样做?您可以编写一个程序来执行此操作,但是花时间花时间在您的项目本身上工作,而不是编写程序来维护您的项目吗?
就个人而言,我实际上不介意
std ::
前缀。我喜欢它不拥有它。我不知道那是因为它是明确的,并对我说:“这不是我的代码...我正在使用标准库”,或者它是否是其他东西,但我认为它看起来更好。鉴于我直到最近才进入C ++(使用C ++(在更长的时间里),C是我有史以来最喜欢的语言,在汇编之上是我最喜欢的语言)。还有另一件事,尽管它与上述内容有些相关,而其他人则指出了什么。虽然这可能是不好的练习,但我有时保留
std ::名称
用于标准库版本和针对特定程序的实现名称。是的,的确,这可能会咬您并用力地咬您,但这一切都取决于我从头开始启动这个项目,而我是唯一的程序员。示例:i Overloadstd :: String
并将其调用String
。我有帮助的补充。我之所以这样做,部分原因是我的C和Unix(+ Linux)倾向于较低的名称。除此之外,您还可以拥有名称空间别名。这是一个可能没有提及的有用的示例。我使用C ++ 11标准,专门用于LIBSTDC ++。好吧,它没有完整的
std :: Regex
支持。当然,它会编译,但是它沿其线路的异常是程序员的终结中的一个例外。但这是缺乏实施。因此,这就是我解决的方法。安装boost的正则正则链条,然后将其链接到。然后,我执行以下操作,以便当libstdc ++完全实现时,我只需要删除此块,而代码保持不变:
我不会争论这是一个坏主意还是不是。但是,我会争辩说,它可以使它保持清洁,以便我的项目,与此同时,它具有特定的内容:是的,我必须使用boost,,但我像LIBSTDC ++最终将拥有它。是的,启动自己的项目并从一开始就以标准(...)开始,在帮助维护,开发以及项目所涉及的所有内容方面有很长的路要走!
只是为了澄清一些事情:我实际上并不认为使用class的名称/ stl 故意,更具体地代替。字符串是例外(我不喜欢“字符串”的想法,请忽略第一个,上方或第二个,如果您必须的话,如果您需要的话,请忽略它。
实际上,我仍然对C偏见,并且对C ++有偏见。保留细节,我在工作中工作的大部分都更适合C(但这是一个很好的练习,也是使自己A的好方法。学习另一种语言和b。请不要偏爱对象/class/class/ett,这也许更好地说明了不太封闭,不太自大,更接受。)。但是,什么 有用的是一些已经提出的建议:我确实使用列表(这是相当通用的,不是吗?我要使用名称空间std; 进行
,因此,我更喜欢在控制方面进行特定,并且知道如果我打算将其作为标准用途,那么我将不得不指定它。简单地说:不允许假设。
至于使Boost的REGEX部分
STD
。我这样做是为了将来集成,而且 - 再次承认这是偏见 - 我认为它不像boost :: Regex :: ... ...
那样丑陋。确实,这对我来说是另一件事。 C ++中有很多事情,我仍然尚未完全接受外观和方法(另一个示例:variadic模板与var参数[尽管我承认variadic模板非常有用!])。即使我接受的那些很困难,和我仍然有问题。I agree with others – it is asking for name clashes, ambiguities and then the fact is it is less explicit. While I can see the use of
using
, my personal preference is to limit it. I would also strongly consider what some others pointed out:If you want to find a function name that might be a fairly common name, but you only want to find it in the
std
namespace (or the reverse – you want to change all calls that are not in namespacestd
, namespaceX
, ...), then how do you propose to do this?You could write a program to do it, but wouldn't it be better to spend time working on your project itself rather than writing a program to maintain your project?
Personally, I actually don't mind the
std::
prefix. I like the look more than not having it. I don't know if that is because it is explicit and says to me "this isn't my code... I am using the standard library" or if it is something else, but I think it looks nicer. This might be odd given that I only recently got into C++ (used and still do C and other languages for much longer and C is my favourite language of all time, right above assembly).There is one other thing although it is somewhat related to the above and what others point out. While this might be bad practise, I sometimes reserve
std::name
for the standard library version and name for program-specific implementation. Yes, indeed this could bite you and bite you hard, but it all comes down to that I started this project from scratch, and I'm the only programmer for it. Example: I overloadstd::string
and call itstring
. I have helpful additions. I did it in part because of my C and Unix (+ Linux) tendency towards lower-case names.Besides that, you can have namespace aliases. Here is an example of where it is useful that might not have been referred to. I use the C++11 standard and specifically with libstdc++. Well, it doesn't have complete
std::regex
support. Sure, it compiles, but it throws an exception along the lines of it being an error on the programmer's end. But it is lack of implementation.So here's how I solved it. Install Boost's regex, and link it in. Then, I do the following so that when libstdc++ has it implemented entirely, I need only remove this block and the code remains the same:
I won't argue on whether that is a bad idea or not. I will however argue that it keeps it clean for my project and at the same time makes it specific: True, I have to use Boost, but I'm using it like the libstdc++ will eventually have it. Yes, starting your own project and starting with a standard (...) at the very beginning goes a very long way with helping maintenance, development and everything involved with the project!
Just to clarify something: I don't actually think it is a good idea to use a name of a class/whatever in the STL deliberately and more specifically in place of. The string is the exception (ignore the first, above, or second here, pun if you must) for me as I didn't like the idea of 'String'.
As it is, I am still very biased towards C and biased against C++. Sparing details, much of what I work on fits C more (but it was a good exercise and a good way to make myself a. learn another language and b. try not be less biased against object/classes/etc which is maybe better stated as less closed-minded, less arrogant, and more accepting.). But what is useful is what some already suggested: I do indeed use list (it is fairly generic, is it not ?), and sort (same thing) to name two that would cause a name clash if I were to do
using namespace std;
, and so to that end I prefer being specific, in control and knowing that if I intend it to be the standard use then I will have to specify it. Put simply: no assuming allowed.And as for making Boost's regex part of
std
. I do that for future integration and – again, I admit fully this is bias - I don't think it is as ugly asboost::regex:: ...
. Indeed, that is another thing for me. There are many things in C++ that I still have yet to come to fully accept in looks and methods (another example: variadic templates versus var arguments [though I admit variadic templates are very very useful!]). Even those that I do accept it was difficult, and I still have issues with them.从我的经验来看,如果您有多个使用Say的库
Cout
,但是出于不同的目的,您可以使用错误的cout
。例如,如果我键入
,请使用namespace std;
and使用namesp eletherlib;
and offecout
(恰好在两者中) ,而不是std :: cout
(或'otherlib :: cout'
),您可能会使用错误的一个并获取错误。使用std :: cout
更有效和有效。From my experiences, if you have multiple libraries that uses say,
cout
, but for a different purpose you may use the wrongcout
.For example, if I type in,
using namespace std;
andusing namespace otherlib;
and type justcout
(which happens to be in both), rather thanstd::cout
(or'otherlib::cout'
), you might use the wrong one, and get errors. It's much more effective and efficient to usestd::cout
.我认为在所有情况下,这都不是不良习惯,但是在使用时,您需要小心。如果您正在编写库,则可能应该使用带有名称空间的范围分辨率运算符,以防止您的库与其他图书馆捆绑。对于应用程序级代码,我没有发现任何问题。
I do not think it is necessarily bad practice under all conditions, but you need to be careful when you use it. If you're writing a library, you probably should use the scope resolution operators with the namespace to keep your library from butting heads with other libraries. For application level code, I don't see anything wrong with it.
使用不合格的导入标识符,您需要外部搜索工具,例如 grep ,以找出声明标识符的位置。这使得有关程序正确性的推理更加困难。
With unqualified imported identifiers you need external search tools like grep to find out where identifiers are declared. This makes reasoning about program correctness harder.
为什么要避免使用命名空间std; ?
原因1:避免名称碰撞。
,因为C ++标准库很大并且不断扩展在C ++中用于减少名称碰撞。当您使用“使用命名空间std”时,您将批发所有内容。
这就是为什么“使用名称空间std”;永远不会出现在任何专业代码中。
原因2:汇编失败。
因为它将数百件(类,方法,常数,模板等)拉到 std namepace中定义的东西(类,方法,常数,模板等)。它这样做,不仅是针对写入“使用名称空间std”本身的文件,而且还用于递归包含它的任何文件。这很容易导致偶然的 odr 违规和难以实现的违规行为和难以访问debug compiler/linker错误。
示例:
在全局名称空间中声明函数“ max”时,使用std名称空间。
由于您没有使用 cmath 标题,因此一切似乎都很好。
当其他人包括您的文件和 cmath 标题时,他们的代码意外构建,因为在全局名称空间中有两个功能,名称为“ max”。
原因3:将来可能无法使用。
更糟糕的是,您无法预测将来对 std :: 名称空间的更改。这意味着,如果新添加的符号与代码中的某些内容发生冲突,那么今天功能的代码可能会在以后的稍后起作用。
原因4:难以维护和调试。
使用命名空间std; 可能会产生难以维护和难以删除的代码。这是由于以下事实:某些方面的来源并不总是很明显。如果开发人员使用术语“字符串”而无需更多说明,则可能指的是 std :: string 类或唯一的字符串类。
带有
namespace std
的代码没有
namepace
,但是您可以使用,如果,
您可以使用该简短教程或程序等,等等。
Why should
using namespace std;
be avoided?Reason 1: To avoid name collision.
Because the C++ standard library is large and constantly expanding, namespaces in C++ are used to lessen name collisions. You are importing everything wholesale when you use "using namespace std;".
That's why "using namespace std;" will never appear in any professional code.
Reason 2: Failed compilation.
Because it pulls the hundreds of things (classes, methods, constants, templates, etc.) defined in the std namespace into the global namespace. And it does so, not just for the file that writes “using namespace std” itself, but also for any file that includes it, recursively. This can very easily lead to accidental ODR violations and hard-to-debug compiler/linker errors.
Example:
You use the std namespace when you declare the function "max" in the global namespace.
Since you aren't using the cmath header, everything appears to be working well.
When someone else includes your file and the cmath header, their code unexpectedly fails to build because there are two functions with the name "max" in the global namespace.
Reason 3: May not work in future.
Even worse, you can't predict what changes will be made to the std:: namespace in the future. This means that code that functions today might cease to function later if a newly added symbol clashes with something in your code.
Reason 4: Difficult to maintain and debug.
The use of namespace std; can produce difficult-to-maintain and difficult-to-debug code. This is due to the fact that it is not always obvious where certain aspects come from. A developer might be referring to the std::string class or a unique string class if they use the term "string" without more explanation.
Code with
namespace std
Without
namespace
But you can use if,
you can use that if want to make short tutorials or programs, etc.
no problem using "using namespace std" in your source file when you make heavy use of the namespace and know for sure that nothing will collide.
这通常被称为全球名称空间污染。当多个命名空间具有带有签名的功能名称相同的功能名称时,可能会发生问题,那么编译器决定要拨打哪个名称是模棱两可的,并且当您使用函数调用指定名称空间(如
)时,可以避免所有这些。 std :: cout
。This is often known as global namespace pollution. Problems may occur when more than one namespace has the same function name with signature, then it will be ambiguous for the compiler to decide which one to call and this all can be avoided when you are specifying the namespace with your function call like
std::cout
.要回答您的问题,我实际上是这样看的:许多程序员(并非全部)调用名称空间std。因此,人们应该习惯于不使用构成与名称空间性标准相同名称的事物。这是一笔巨大的批准,但与可能会严格说出的可能相干词和化名的数量相比,这并不是很多。
我的意思是说……说“不要依靠这个存在”只是让您依靠它不存在。您将不断遇到借用代码片段并不断修理它们的问题。只要将用户定义和借来的东西保持在有限的范围内,并且要对全球群体非常差异(老实说,Globals几乎应该总是为“现在的汇编,以后的理智”而成为最后的手段)。确实,我认为这是您老师的不好建议,因为使用性病将适用于“ COUT”和“ STD :: COUT”,但不使用STD仅适用于“ STD :: COUT”。您不会总是很幸运地编写自己的所有代码。
注意:直到您真正了解编译器的工作方式,请不要过多地关注效率问题。有了一些经验,您就不必在意识到他们能够将良好的代码概括为简单的东西之前就不必了解它们。每一点都像您在C中写整个内容一样简单。良好的代码仅是必要的复杂。
To answer your question I look at it this way practically: a lot of programmers (not all) invoke namespace std. Therefore one should be in the habit of NOT using things that impinge or use the same names as what is in the namespace std. That is a great deal granted, but not so much compared to the number of possible coherent words and pseudonyms that can be come up with strictly speaking.
I mean really... saying "don't rely on this being present" is just setting you up to rely on it NOT being present. You are constantly going to have issues borrowing code snippets and constantly repairing them. Just keep your user-defined and borrowed stuff in limited scope as they should be and be VERY sparing with globals (honestly globals should almost always be a last resort for purposes of "compile now, sanity later"). Truly I think it is bad advice from your teacher because using std will work for both "cout" and "std::cout" but NOT using std will only work for "std::cout". You will not always be fortunate enough to write all your own code.
NOTE: Don't focus too much on efficiency issues until you actually learn a little about how compilers work. With a little experience coding you don't have to learn that much about them before you realize how much they are able to generalize good code into something something simple. Every bit as simple as if you wrote the whole thing in C. Good code is only as complex as it needs to be.
考虑两个称为foo and bar的库:
一切正常,您可以从foo中调用
blah()
,而quux()
bar毫无问题。但是有一天,您可以升级到新版本的Foo 2.0,该版本现在提供了一个称为quux()
的函数。现在,您已经发生了冲突:FOO 2.0和BAR导入Quux()
进入您的全局名称空间。这将需要一些努力来修复,尤其是在功能参数恰好匹配的情况下。如果您使用过
foo :: blah()
andbar :: quux()
,那么foo :: quux()
的介绍将是一个非事件。Consider two libraries called Foo and Bar:
Everything works fine, and you can call
Blah()
from Foo andQuux()
from Bar without problems. But one day you upgrade to a new version of Foo 2.0, which now offers a function calledQuux()
. Now you've got a conflict: Both Foo 2.0 and Bar importQuux()
into your global namespace. This is going to take some effort to fix, especially if the function parameters happen to match.If you had used
foo::Blah()
andbar::Quux()
, then the introduction offoo::Quux()
would have been a non-event.它可能会变得更糟比 greg写作!
图书馆FOO 2.0可以引入一个函数,
quux()
,对于quux()
>bar :: quux(quux( )
您的代码已打电话多年。然后,您的 代码仍然编译 ,但是 它默默地称为错误的函数 ,并且上帝知道什么。那和事情一样糟糕。请记住,
std
名称空间具有大量标识符,其中许多是非常 common的标识符(thinklist
,sort 代码>,
字符串
,iterator
等)也很可能出现在其他代码中。如果您不太可能考虑:有一个问题在堆栈溢出上,这几乎是正确的(应得的错误的功能)省略
std ::
前缀)大约在我给出答案后半年。 在这里是一个问题的另一个最新示例。因此,这是一个真正的问题。
这是另一个数据点:很多年前,我还发现它很烦人,必须将标准库中的所有内容都带有
std ::
。然后,我在一个项目中工作,一开始就确定使用指令和声明两种均被禁止使用功能范围。猜怎么着?我们大多数人花了几周的时间才习惯编写前缀,几周后,我们中的大多数人甚至同意它实际上使代码更可读。这样做是有原因的: 您不喜欢缩短还是更长的散文是主观的,但是前缀客观地增加了代码。发现更容易查看所引用哪个标识符。
在十年的时间里,该项目越来越多地拥有数百万行代码。由于这些讨论一次又一次进行,因此我曾经很好奇(允许的)功能 - cope 使用实际使用的频率。我抓住了它的来源,只找到了使用它的一个或二十二个地方。对我来说,这表明,一旦尝试过,开发人员就找不到
std ::
痛苦的痛苦,即使在允许使用的情况下,甚至每100 kloc都使用指令。最重要的是:明确的前缀一切都不会造成任何伤害,几乎没有习惯,并且具有客观的优势。特别是,它使编译器和人类读者可以更容易解释代码 - 这可能是编写代码时的主要目标。
It can get worse than what Greg wrote!
Library Foo 2.0 could introduce a function,
Quux()
, that is an unambiguously better match for some of your calls toQuux()
than thebar::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 (thinklist
,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.So this is a real problem.
Here's one more data point: Many, many years ago, I also used to find it annoying having to prefix everything from the standard library with
std::
. Then I worked in a project where it was decided at the start that bothusing
directives and declarations are banned except for function scopes. Guess what? It took most of us very few weeks to get used to writing the prefix, and after a few more weeks most of us even agreed that it actually made the code more readable. There's a reason for that: Whether you like shorter or longer prose is subjective, but the prefixes objectively add clarity to the code. Not only the compiler, but you, too, find it easier to see which identifier is referred to.In a decade, that project grew to have several million lines of code. Since these discussions come up again and again, I once was curious how often the (allowed) function-scope
using
actually was used in the project. I grep'd the sources for it and only found one or two dozen places where it was used. To me this indicates that, once tried, developers don't findstd::
painful enough to employ using directives even once every 100 kLoC even where it was allowed to be used.Bottom line: Explicitly prefixing everything doesn't do any harm, takes very little getting used to, and has objective advantages. In particular, it makes the code easier to interpret by the compiler and by human readers — and that should probably be the main goal when writing code.
使用名称空间在类的标题文件中放置
的问题是,它迫使任何想要使用您的类(通过包括标头文件)的人也可以“使用”(即看到所有内容)那些其他名称空间。
但是,您可能可以随时在(私有) *.cpp文件中列出使用语句。
当心有些人不同意我的意见“自由”这样 - 因为尽管使用在cpp文件中使用语句的 比标题更好(因为它没有 T会影响包含您的标头文件的人),他们认为它仍然不是 good (因为取决于代码,它可能会使类实现更难以维护)。 此c ++ super-faq条目说,
FAQ提出了两种替代方法:
a使用销量:
只是键入std ::
The problem with putting
using namespace
in the header files of your classes is that it forces anyone who wants to use your classes (by including your header files) to also be 'using' (i.e. seeing everything in) those other namespaces.However, you may feel free to put a using statement in your (private) *.cpp files.
Beware that some people disagree with my saying "feel free" like this -- because although a
using
statement in a cpp file is better than in a header (because it doesn't affect people who include your header file), they think it's still not good (because depending on the code it could make the implementation of the class more difficult to maintain). This C++ Super-FAQ entry says,The FAQ suggests two alternatives:
A using-declaration:
Just typing std::
我最近遇到了有关 Visual  stutio  2010 。事实证明,几乎所有的源文件都有这两行:
很多 Boost 功能已进入C ++ 0x标准,并且Visual&nbsp“ Studio  2010具有很多C ++ 0x功能,因此突然间,这些程序没有编译。
因此,避免使用命名空间X; 是对未来预处理的一种形式,这是确保更改库和/或使用中标题文件的一种方式,不会破坏程序。
I recently ran into a complaint about Visual Studio 2010. It turned out that pretty much all the source files had these two lines:
A lot of Boost features are going into the C++0x standard, and Visual Studio 2010 has a lot of C++0x features, so suddenly these programs were not compiling.
Therefore, avoiding
using namespace X;
is a form of future-proofing, a way of making sure a change to the libraries and/or header files in use is not going to break a program.简短版本:不要使用声明或标题文件中的指令使用全局
。随时在实现文件中使用它们。这是 herb sutter and andrei alexandrescu 必须在 C ++编码标准(强调重点是我的):
Short version: don't use global
using
declarations or directives in header files. Feel free to use them in implementation files. Here's what Herb Sutter and Andrei Alexandrescu have to say about this issue in C++ Coding Standards (bolding for emphasis is mine):一个人不应在全局范围,尤其是标题中使用指令使用
。但是,在某些情况下,即使在标题文件中也是合适的:
这比显式资格(
std :: sin
,std :: cos
...),因为它较短并且具有与用户定义的浮点类型一起工作的能力(通过(adl))。One shouldn't use the
using
directive at the global scope, especially in headers. However, there are situations where it is appropriate even in a header file:This is better than explicit qualification (
std::sin
,std::cos
...), because it is shorter and has the ability to work with user defined floating point types (via argument-dependent lookup (ADL)).在全球范围内不要使用它,
只有当使用全球时,才被认为是“不良”。因为:
时,读者很难看到特定标识符的来源。
您可能不知道您抓住的所有东西 - 当您添加另一个
#include 或移至新的C ++修订版,您可能会发现您不知道的名称冲突。
您可以在本地使用它
,并在本地(几乎)自由使用。当然,这可以阻止您重复
std ::
- 重复也很不好。在 c ++ 03 中使用它本地使用的成语
,有一个成语 - 样板代码 - 用于实现您的类。建议您实际上使用local
使用命名空间std;
- 或至少使用std :: swap; swap; :这确实有以下魔术:
std ::交换
<代码>值_ ,即void std :: swap(int,int)
。void交换(Child&amp;,child&amp;)
实施的编译器将选择它。void std :: swap(child&amp;,child&amp;)
,并尝试最佳交换这些。使用 C ++ 11 没有理由再使用此模式了。更改了
std ::交换
的实现,以找到潜在的过载并选择它。Do not use it globally
It is considered "bad" only when used globally. Because:
using namespace xyz;
.using namespace std;
you might not be aware of all the stuff you grab -- and when you add another#include
or move to a new C++ revision you might get name conflicts you were not aware of.You may use it locally
Go ahead and use it locally (almost) freely. This, of course, prevents you from repetition of
std::
-- and repetition is also bad.An idiom for using it locally
In C++03 there was an idiom -- boilerplate code -- for implementing a
swap
function for your classes. It was suggested that you actually use a localusing namespace std;
-- or at leastusing std::swap;
:This does the following magic:
std::swap
forvalue_
, i.e.void std::swap(int, int)
.void swap(Child&, Child&)
implemented the compiler will choose it.void std::swap(Child&,Child&)
and try its best swapping these.With C++11 there is no reason to use this pattern any more. The implementation of
std::swap
was changed to find a potential overload and choose it.如果导入正确的标头文件,则突然有名称,例如
hex
,
,left
plus
或count
在您的全局范围中。如果您不知道std ::
包含这些名称,这可能会令人惊讶。如果您还尝试在本地使用这些名称,则可能会导致一些混乱。如果所有标准内容都在其自己的名称空间中,则不必担心与代码或其他库的名称碰撞。
If you import the right header files you suddenly have names like
hex
,left
,plus
orcount
in your global scope. This might be surprising if you are not aware thatstd::
contains these names. If you also try to use these names locally it can lead to quite some confusion.If all the standard stuff is in its own namespace you don't have to worry about name collisions with your code or other libraries.
另一个原因是惊喜。
如果我看到
cout&lt;&lt; blah
,而不是std :: cout&lt;&lt; blah
我认为:这是什么cout
?它是普通cout
吗?这是特别的吗?Another reason is surprise.
If I see
cout << blah
, instead ofstd::cout << blah
I think: What is thiscout
? Is it the normalcout
? Is it something special?我同意它不应在全球使用,但是在本地使用它并不是那么邪恶,例如
namepace
。这是“ C ++编程语言” 的一个示例:在此示例中,我们解决了潜在的名称冲突和由其组成引起的歧义。
名称在此明确声明(包括使用
his_lib :: string
诸如使用解析声明的名称)优先于在另一个范围内使用的名称(使用名称sher_lib
) )。
I agree that it should not be used globally, but it's not so evil to use locally, like in a
namespace
. Here's an example from "The C++ Programming Language":In this example, we resolved potential name clashes and ambiguities arising from their composition.
Names explicitly declared there (including names declared by using-declarations like
His_lib::String
) take priority over names made accessible in another scope by a using-directive (using namespace Her_lib
).经验丰富的程序员使用任何解决问题的方法,并避免出现新问题的任何问题,并且由于这个确切的原因,他们避免使用领域的标头文件级别。
经验丰富的程序员还尝试避免源文件中的名称的完全资格。这样做的一个小原因是,除非有充分的理由,否则编写更多代码时,编写更多代码并不优雅。造成这种情况的主要原因是关闭与参数有关的查找(ADL)。
这些是什么好理由?有时,程序员明确想关闭ADL,而其他时候他们想歧义。
因此,以下内容是可以的:
Experienced programmers use whatever solves their problems and avoid whatever creates new problems, and they avoid header-file-level using-directives for this exact reason.
Experienced programmers also try to avoid full qualification of names inside their source files. A minor reason for this is that it's not elegant to write more code when less code is sufficient unless there are good reasons. A major reason for this is turning off argument-dependent lookup (ADL).
What are these good reasons? Sometimes programmers explicitly want to turn off ADL, other times they want to disambiguate.
So the following are OK:
我也认为这是一种不好的做法。为什么?仅一天,我就认为名称空间的功能就是分割东西,因此我不应该将所有东西都扔进一个全球袋子而破坏。
但是,如果我经常使用“ cout”和“ cin”,我会写:
使用std :: cout;在.cpp文件中使用std :: cin;
(在标头文件中都不在#include
传播时,它从不在标题文件中。我认为没有一个理智会命名流COUT
或cin
。 )I also consider it a bad practice. Why? Just one day I thought that the function of a namespace is to divide stuff, so I shouldn't spoil it with throwing everything into one global bag.
However, if I often use 'cout' and 'cin', I write:
using std::cout; using std::cin;
in the .cpp file (never in the header file as it propagates with#include
). I think that no one sane will ever name a streamcout
orcin
. ;)很高兴看到代码并知道它的作用。如果我看到
std :: cout
我知道那是cout
std
库的流。如果我看到cout
,那么我不知道。 可以是cout
std
库的流。或者可能有一个int cout = 0;
在同一函数中高十行。或该文件中的static
变量名为cout
。可能是什么。现在采用一百万行代码基库,这并不是特别大,您正在寻找一个错误,这意味着您知道这一百万行中有一行不做应该做的事情。
cout&lt;&lt; 1;
可以读取static int
命名cout
,将其向左移动一点,然后丢弃结果。寻找错误,我必须检查一下。您能看到我真的更喜欢看std :: Cout
吗?如果您是老师,并且不必为谋生而写任何代码,那么这似乎是一个非常好主意。我喜欢看代码(1)我知道它的作用;而且,(2)我有信心写它的人知道它的作用。
It's nice to see code and know what it does. If I see
std::cout
I know that's thecout
stream of thestd
library. If I seecout
then I don't know. It could be thecout
stream of thestd
library. Or there could be anint cout = 0;
ten lines higher in the same function. Or astatic
variable namedcout
in that file. It could be anything.Now take a million line code base, which isn't particularly big, and you're searching for a bug, which means you know there is one line in this one million lines that doesn't do what it is supposed to do.
cout << 1;
could read astatic int
namedcout
, shift it to the left by one bit, and throw away the result. Looking for a bug, I'd have to check that. Can you see how I really really prefer to seestd::cout
?It's one of these things that seem a really good idea if you are a teacher and never had to write and maintain any code for a living. I love seeing code where (1) I know what it does; and, (2) I'm confident that the person writing it knew what it does.
这一切都是关于管理复杂性。使用命名空间会吸引您不想要的东西,因此可能会更难调试(我说)。在整个地方使用STD ::更难阅读(更多文本等)。
课程的马匹 - 管理您的复杂性,如何最好和有能力。
It's all about managing complexity. Using the namespace will pull things in that you don't want, and thus possibly make it harder to debug (I say possibly). Using std:: all over the place is harder to read (more text and all that).
Horses for courses - manage your complexity how you best can and feel able.
请
注意,这是一个简单的示例。如果您的文件具有20个包含和其他导入的文件,则需要大量的依赖项来弄清楚问题。最糟糕的是,您可以根据冲突的定义在其他模块中获得无关的错误。
这不是可怕的,但是您会通过在标头文件或全局名称空间中使用它来节省自己的头痛。在非常有限的范围内进行操作可能是正确的,但是我从来没有遇到过额外的五个字符来阐明我的功能来自何处的问题。
Consider
Note that this is a simple example. If you have files with 20 includes and other imports, you'll have a ton of dependencies to go through to figure out the problem. The worse thing about it is that you can get unrelated errors in other modules depending on the definitions that conflict.
It's not horrible, but you'll save yourself headaches by not using it in header files or the global namespace. It's probably all right to do it in very limited scopes, but I've never had a problem typing the extra five characters to clarify where my functions are coming from.
一个具体的例子来澄清关注点。想象一下,您有一个有两个库,
foo
和bar
,每个库都有自己的名称空间:现在,假设您使用
foo
和<代码> bar 在您自己的程序中一起使用如下:此时一切都很好。当您运行程序时,它会“做某事”。但是后来您更新
bar
,假设它已经改变了:此时,您将收到一个编译器错误:
因此,您需要进行一些维护以澄清“ a”的含义<代码> foo :: a 。这是不希望的,但是幸运的是,这很容易(只需在所有调用中添加
foo ::
编译器标记为模棱两可的)。
但是,想象一个替代场景,bar更改为看起来像这样:
此时,您的调用
a(42)
突然绑定到bar :: A
而不是> foo :: a
,而不是做“某件事”,而是做“完全不同的事”。没有编译器警告或任何内容。您的程序只是默默地开始做与以前完全不同的事情。当您使用名称空间时,您会冒着这样的场景的危险,这就是为什么人们使用名称空间感到不舒服的原因。命名空间中的东西越多,冲突的风险就越大,因此,使用名称空间
std
(由于该名称空间中的事物数),人们可能比其他名称空间更加不舒服。最终,这是可靠性/可靠性之间的权衡。可读性也可能因素,但是我可以看到这两种方式的论据。通常,我会说可靠性和可维护性更为重要,但是在这种情况下,您将不断支付撰写能力成本,以产生相当罕见的可靠性/可维护性的影响。 “最佳”权衡将决定您的项目和优先事项。
A concrete example to clarify the concern. Imagine you have a situation where you have two libraries,
foo
andbar
, each with their own namespace:Now let's say you use
foo
andbar
together in your own program as follows:At this point everything is fine. When you run your program it 'Does something'. But later you update
bar
and let's say it has changed to be like:At this point you'll get a compiler error:
So you'll need to do some maintenance to clarify that 'a' meant
foo::a
. That's undesirable, but fortunately it is pretty easy (just addfoo::
in front of all calls toa
that the compiler marks as ambiguous).But imagine an alternative scenario where bar changed instead to look like this instead:
At this point your call to
a(42)
suddenly binds tobar::a
instead offoo::a
and instead of doing 'something' it does 'something completely different'. No compiler warning or anything. Your program just silently starts doing something completely different than before.When you use a namespace you're risking a scenario like this, which is why people are uncomfortable using namespaces. The more things in a namespace, the greater the risk of conflict, so people might be even more uncomfortable using namespace
std
(due to the number of things in that namespace) than other namespaces.Ultimately this is a trade-off between writability vs. reliability/maintainability. Readability may factor in also, but I could see arguments for that going either way. Normally I would say reliability and maintainability are more important, but in this case you'll constantly pay the writability cost for an fairly rare reliability/maintainability impact. The 'best' trade-off will determine on your project and your priorities.